@lvce-editor/extension-management-worker 4.74.3 → 4.75.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/dist/extensionManagementWorkerMain.js +1088 -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,11 +2317,11 @@ 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
|
};
|
|
2197
|
-
const fileSystemMethods = new Set(['readFile', 'readDirWithFileTypes', 'stat', 'exists', 'writeFile', 'mkdir', 'remove', 'rename', 'copy', 'getBlob']);
|
|
2324
|
+
const fileSystemMethods = new Set(['readFile', 'readDirWithFileTypes', 'stat', 'exists', 'writeFile', 'mkdir', 'remove', 'rename', 'copy', 'getBlob', 'getFileHashes']);
|
|
2198
2325
|
const createFileSystemPort = async (application, port, extensionId) => {
|
|
2199
2326
|
const services = getServices(application);
|
|
2200
2327
|
const version = extensionId === undefined ? 0 : services.extensionVersions.get(extensionId) || 0;
|
|
@@ -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
|
}
|
|
@@ -3416,11 +3547,11 @@ const disposeExtensionApplication = async applicationId => {
|
|
|
3416
3547
|
const ids = new Set([...getIds(applicationId), ...getPendingExtensionIds(application)]);
|
|
3417
3548
|
const runtimes = ids.values().map(id => ({
|
|
3418
3549
|
id,
|
|
3419
|
-
rpc: get$
|
|
3550
|
+
rpc: get$2(id, applicationId)
|
|
3420
3551
|
})).toArray();
|
|
3421
3552
|
// Invalidate pending activations and extension callbacks before awaiting teardown.
|
|
3422
3553
|
removeApplication(applicationId);
|
|
3423
|
-
clear(applicationId);
|
|
3554
|
+
clear$1(applicationId);
|
|
3424
3555
|
resetAllExtensionActivations(application);
|
|
3425
3556
|
reset(applicationId);
|
|
3426
3557
|
const results = await Promise.allSettled([dispose(application), ...runtimes.map(async ({
|
|
@@ -3428,7 +3559,7 @@ const disposeExtensionApplication = async applicationId => {
|
|
|
3428
3559
|
rpc
|
|
3429
3560
|
}) => {
|
|
3430
3561
|
const runtimeId = getRuntimeId(id, application);
|
|
3431
|
-
const disposal = await Promise.allSettled([Promise.try(() => rpc?.dispose()), invoke('LaunchIsolatedExtensionHostWorker.disposeIsolatedExtensionHostWorker', runtimeId)]);
|
|
3562
|
+
const disposal = await Promise.allSettled([Promise.try(() => rpc?.dispose()), invoke$2('LaunchIsolatedExtensionHostWorker.disposeIsolatedExtensionHostWorker', runtimeId)]);
|
|
3432
3563
|
const errors = disposal.filter(result => result.status === 'rejected').map(result => result.reason);
|
|
3433
3564
|
if (errors.length > 0) {
|
|
3434
3565
|
throw new AggregateError(errors, `Failed to dispose extension ${id}`);
|
|
@@ -3463,7 +3594,7 @@ const enableWorkspaceExtension = async id => {
|
|
|
3463
3594
|
|
|
3464
3595
|
/* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
|
|
3465
3596
|
|
|
3466
|
-
const getExtensionId$
|
|
3597
|
+
const getExtensionId$1 = extension => {
|
|
3467
3598
|
return extension.id || interExtensionId(extension.uri || extension.path || '');
|
|
3468
3599
|
};
|
|
3469
3600
|
const contributesCommand = (extension, id) => {
|
|
@@ -3478,8 +3609,11 @@ const getRpcForCommand = async (extensionsState, id, platform) => {
|
|
|
3478
3609
|
if (!extension) {
|
|
3479
3610
|
return undefined;
|
|
3480
3611
|
}
|
|
3481
|
-
|
|
3482
|
-
|
|
3612
|
+
if (extension.workspaceTransport?.command === id) {
|
|
3613
|
+
throw new Error('Workspace transports can only be called by extension management');
|
|
3614
|
+
}
|
|
3615
|
+
const extensionId = getExtensionId$1(extension);
|
|
3616
|
+
const existingRpc = get$2(extensionId, extensionsState.applicationId);
|
|
3483
3617
|
if (existingRpc) {
|
|
3484
3618
|
return existingRpc;
|
|
3485
3619
|
}
|
|
@@ -3488,7 +3622,7 @@ const getRpcForCommand = async (extensionsState, id, platform) => {
|
|
|
3488
3622
|
} else {
|
|
3489
3623
|
await activateByEvent(`onCommand:${id}`, '', platform, extensionsState);
|
|
3490
3624
|
}
|
|
3491
|
-
return get$
|
|
3625
|
+
return get$2(extensionId, extensionsState.applicationId);
|
|
3492
3626
|
};
|
|
3493
3627
|
const executeRendererCommand = (id, args, applicationId) => {
|
|
3494
3628
|
if (applicationId !== undefined) {
|
|
@@ -3623,33 +3757,6 @@ const executeLanguageServerCompletion = async (rpc, extension, textDocument, off
|
|
|
3623
3757
|
return result.map(sanitizeCompletionItem).filter(item => item !== undefined);
|
|
3624
3758
|
};
|
|
3625
3759
|
|
|
3626
|
-
const getExtensionId$1 = extension => {
|
|
3627
|
-
return extension.id || interExtensionId(extension.uri || extension.path || '');
|
|
3628
|
-
};
|
|
3629
|
-
const getAbsolutePath = (extension, assetDir, platform) => {
|
|
3630
|
-
return getExtensionAbsolutePath(getExtensionId$1(extension), extension.isWeb === true, extension.builtin === true, extension.path || extension.uri || '', extension.browser || '', getOrigin(), platform, assetDir);
|
|
3631
|
-
};
|
|
3632
|
-
const getRpc$1 = async (extension, assetDir, platform, activationEvent = '', getOrCreate = getOrCreateIsolatedExtensionHostWorker, notify = notifyRunningExtensionsChanged) => {
|
|
3633
|
-
if (extension.applicationId !== undefined) {
|
|
3634
|
-
assertCurrentApplication(extension);
|
|
3635
|
-
}
|
|
3636
|
-
const extensionId = getExtensionId$1(extension);
|
|
3637
|
-
const existingRpc = get$3(extensionId, extension.applicationId);
|
|
3638
|
-
if (existingRpc) {
|
|
3639
|
-
return existingRpc;
|
|
3640
|
-
}
|
|
3641
|
-
handleRpcInfos(extension, platform);
|
|
3642
|
-
const absolutePath = getAbsolutePath(extension, assetDir, platform);
|
|
3643
|
-
const contentSecurityPolicy = getContentSecurityPolicy(extension.contentSecurityPolicy, absolutePath, extension.rpc);
|
|
3644
|
-
const rpc = await activateIsolatedExtension(extensionId, absolutePath, extension.workerName || '', contentSecurityPolicy, activationEvent, getOrCreate, extension.applicationId);
|
|
3645
|
-
if (extension.applicationId === undefined) {
|
|
3646
|
-
notify();
|
|
3647
|
-
} else {
|
|
3648
|
-
notify(extension.applicationId);
|
|
3649
|
-
}
|
|
3650
|
-
return rpc;
|
|
3651
|
-
};
|
|
3652
|
-
|
|
3653
3760
|
/* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */
|
|
3654
3761
|
|
|
3655
3762
|
const contributesCompletionProvider = (extension, languageId) => {
|
|
@@ -4538,7 +4645,7 @@ const getRegisteredOutputChannelIds = snapshot => {
|
|
|
4538
4645
|
return new Set(snapshot.outputChannels.map(outputChannel => outputChannel.id).filter(id => typeof id === 'string'));
|
|
4539
4646
|
};
|
|
4540
4647
|
const getExtensionOutputChannelProviders = async (extension, assetDir, platform) => {
|
|
4541
|
-
const extensionId = getExtensionId$
|
|
4648
|
+
const extensionId = getExtensionId$3(extension);
|
|
4542
4649
|
const rpc = await getRpc$1(extension, assetDir, platform);
|
|
4543
4650
|
let snapshot;
|
|
4544
4651
|
try {
|
|
@@ -4590,7 +4697,7 @@ const resolveOutputChannel = async (extensionsState, uri) => {
|
|
|
4590
4697
|
platform
|
|
4591
4698
|
} = await getRuntimeContext('', extensionsState.platform);
|
|
4592
4699
|
const extensions = await getAllExtensionsWithState(extensionsState, assetDir, platform);
|
|
4593
|
-
const extension = extensions.find(candidate => getExtensionId$
|
|
4700
|
+
const extension = extensions.find(candidate => getExtensionId$3(candidate) === extensionId && hasOutputChannels(candidate));
|
|
4594
4701
|
const isContributed = extension?.outputChannels?.some(outputChannel => outputChannel.id === outputChannelId);
|
|
4595
4702
|
if (!extension || !isContributed) {
|
|
4596
4703
|
throw new Error(`Output channel ${outputChannelId} is not contributed by extension ${extensionId}`);
|
|
@@ -4676,7 +4783,7 @@ const disposeViewOnlyExtensionWorker = async (extensionId, rpc) => {
|
|
|
4676
4783
|
if (hasOtherViewInstances(rpc)) {
|
|
4677
4784
|
return;
|
|
4678
4785
|
}
|
|
4679
|
-
if (get$
|
|
4786
|
+
if (get$2(extensionId) !== rpc) {
|
|
4680
4787
|
return;
|
|
4681
4788
|
}
|
|
4682
4789
|
await disposeIsolatedExtensionHostWorker(extensionId);
|
|
@@ -4695,8 +4802,8 @@ const getRpcForView = async (viewId, assetDir, platform, applicationId) => {
|
|
|
4695
4802
|
platform: resolvedPlatform
|
|
4696
4803
|
} = await getRuntimeContext(assetDir, platform);
|
|
4697
4804
|
const extension = await getExtensionForView(viewId, resolvedAssetDir, resolvedPlatform, applicationId);
|
|
4698
|
-
const extensionId = getExtensionId$
|
|
4699
|
-
const existingRpc = get$
|
|
4805
|
+
const extensionId = getExtensionId$3(extension);
|
|
4806
|
+
const existingRpc = get$2(extensionId, applicationId);
|
|
4700
4807
|
// Application teardown and reload own application workers; global view-only disposal does not.
|
|
4701
4808
|
if (existingRpc) {
|
|
4702
4809
|
return {
|
|
@@ -5253,13 +5360,13 @@ const getRemoteUrlForWebView = async (uri, options = {}) => {
|
|
|
5253
5360
|
if (!webView) {
|
|
5254
5361
|
throw new Error(`webview ${options.webViewId} not found`);
|
|
5255
5362
|
}
|
|
5256
|
-
const [rpc, blob] = await Promise.all([createWebViewIpc(webView), invoke('FileSystem.getBlob', uri)]);
|
|
5363
|
+
const [rpc, blob] = await Promise.all([createWebViewIpc(webView), invoke$2('FileSystem.getBlob', uri)]);
|
|
5257
5364
|
const objectUrl = await rpc.invoke('createObjectUrl', blob);
|
|
5258
5365
|
return objectUrl;
|
|
5259
5366
|
};
|
|
5260
5367
|
|
|
5261
5368
|
const getRpcInfo = rpcId => {
|
|
5262
|
-
const info = get$
|
|
5369
|
+
const info = get$3(rpcId);
|
|
5263
5370
|
if (!info) {
|
|
5264
5371
|
throw new Error(`Rpc not found ${rpcId}`);
|
|
5265
5372
|
}
|
|
@@ -5280,7 +5387,7 @@ const getIcon = (extension, manifestView, assetDir, platform) => {
|
|
|
5280
5387
|
if (isAbsoluteIcon(manifestIcon) || !isRelativeIconPath(manifestIcon)) {
|
|
5281
5388
|
return manifestIcon;
|
|
5282
5389
|
}
|
|
5283
|
-
return getAbsolutePath({
|
|
5390
|
+
return getAbsolutePath$1({
|
|
5284
5391
|
...extension,
|
|
5285
5392
|
browser: manifestIcon
|
|
5286
5393
|
}, assetDir, platform);
|
|
@@ -5341,7 +5448,7 @@ const waitForTimeout = async (timeout, sleep) => {
|
|
|
5341
5448
|
const isResponsive = async (rpc, timeout, sleep) => {
|
|
5342
5449
|
return Promise.race([invokePing(rpc), waitForTimeout(timeout, sleep)]);
|
|
5343
5450
|
};
|
|
5344
|
-
const updateTerminatedExtensionStatuses = async (runtimeStatuses, getRpc = get$
|
|
5451
|
+
const updateTerminatedExtensionStatuses = async (runtimeStatuses, getRpc = get$2, timeout = 250, sleep$1 = sleep) => {
|
|
5345
5452
|
const activatedStatuses = Object.values(runtimeStatuses).filter(status => status.status === Activated);
|
|
5346
5453
|
await Promise.all(activatedStatuses.map(async status => {
|
|
5347
5454
|
const rpc = getRpc(status.id);
|
|
@@ -5403,7 +5510,7 @@ const getItems = async rpc => {
|
|
|
5403
5510
|
return rpc.invoke('ExtensionApi.getStatusBarItems');
|
|
5404
5511
|
};
|
|
5405
5512
|
const getStatusBarItems = async applicationId => {
|
|
5406
|
-
const rpcs = getAll(applicationId);
|
|
5513
|
+
const rpcs = getAll$1(applicationId);
|
|
5407
5514
|
const results = await Promise.all(rpcs.map(getItems));
|
|
5408
5515
|
return results.flat();
|
|
5409
5516
|
};
|
|
@@ -5413,7 +5520,7 @@ const getCss = (extension, manifestView, assetDir, platform) => {
|
|
|
5413
5520
|
if (typeof css !== 'string' || css.length === 0) {
|
|
5414
5521
|
return '';
|
|
5415
5522
|
}
|
|
5416
|
-
return getAbsolutePath({
|
|
5523
|
+
return getAbsolutePath$1({
|
|
5417
5524
|
...extension,
|
|
5418
5525
|
browser: css
|
|
5419
5526
|
}, assetDir, platform);
|
|
@@ -5428,7 +5535,7 @@ const getIframe = (extension, manifestView, assetDir, platform) => {
|
|
|
5428
5535
|
credentialless: iframe.credentialless !== false,
|
|
5429
5536
|
csp: iframe.csp || '',
|
|
5430
5537
|
sandbox: Array.isArray(iframe.sandbox) ? iframe.sandbox.filter(item => typeof item === 'string') : ['allow-scripts'],
|
|
5431
|
-
src: getAbsolutePath({
|
|
5538
|
+
src: getAbsolutePath$1({
|
|
5432
5539
|
...extension,
|
|
5433
5540
|
browser: iframe.path
|
|
5434
5541
|
}, assetDir, platform)
|
|
@@ -5459,7 +5566,7 @@ const toView = (extension, manifestView, assetDir, platform) => {
|
|
|
5459
5566
|
...(type && {
|
|
5460
5567
|
type
|
|
5461
5568
|
}),
|
|
5462
|
-
extensionId: getExtensionId$
|
|
5569
|
+
extensionId: getExtensionId$3(extension),
|
|
5463
5570
|
icon: getIcon(extension, manifestView, assetDir, platform),
|
|
5464
5571
|
id,
|
|
5465
5572
|
iframe: getIframe(extension, manifestView, assetDir, platform),
|
|
@@ -5489,7 +5596,7 @@ const shouldLoadViews = extension => {
|
|
|
5489
5596
|
return false;
|
|
5490
5597
|
}
|
|
5491
5598
|
if (!isExtensionIsolated(extension)) {
|
|
5492
|
-
warn(`Extension "${getExtensionId$
|
|
5599
|
+
warn(`Extension "${getExtensionId$3(extension)}" contributes activity bar views but is not isolated. The views will not be shown. Add "isolated": true to extension.json to enable them.`);
|
|
5493
5600
|
return false;
|
|
5494
5601
|
}
|
|
5495
5602
|
return true;
|
|
@@ -5512,7 +5619,7 @@ const getViews = async (assetDir, platform) => {
|
|
|
5512
5619
|
const handleData = () => {};
|
|
5513
5620
|
|
|
5514
5621
|
const invokeHandler = async (extensionId, changes, applicationId) => {
|
|
5515
|
-
const rpc = get$
|
|
5622
|
+
const rpc = get$2(extensionId, applicationId);
|
|
5516
5623
|
if (!rpc) {
|
|
5517
5624
|
unregister(extensionId, applicationId);
|
|
5518
5625
|
return;
|
|
@@ -5533,9 +5640,9 @@ const handleMessagePort = async (port, rpcId) => {
|
|
|
5533
5640
|
messagePort: port
|
|
5534
5641
|
});
|
|
5535
5642
|
if (rpcId === StatusBarWorker) {
|
|
5536
|
-
set$
|
|
5643
|
+
set$2(rpc);
|
|
5537
5644
|
} else if (rpcId === NotificationCenterWorker) {
|
|
5538
|
-
set$
|
|
5645
|
+
set$3(rpc);
|
|
5539
5646
|
}
|
|
5540
5647
|
};
|
|
5541
5648
|
|
|
@@ -5626,7 +5733,7 @@ const defaultDependencies$2 = {
|
|
|
5626
5733
|
activateByEvent: activateByEvent,
|
|
5627
5734
|
createViewInstance: createViewInstance,
|
|
5628
5735
|
disposeExtensionRuntime,
|
|
5629
|
-
getRpc: get$
|
|
5736
|
+
getRpc: get$2,
|
|
5630
5737
|
getRuntimeStatus: getRuntimeStatus$1,
|
|
5631
5738
|
getViewEntries: getEntries,
|
|
5632
5739
|
removeViewInstance: remove,
|
|
@@ -5873,7 +5980,7 @@ const replace = async (application, extensionId, extension) => {
|
|
|
5873
5980
|
assertCurrentApplication(application);
|
|
5874
5981
|
const rpc = remove$1(extensionId, applicationId);
|
|
5875
5982
|
unregister(extensionId, applicationId);
|
|
5876
|
-
const results = await Promise.allSettled([disposeExtension(application, extensionId), Promise.try(() => rpc?.dispose()), invoke('LaunchIsolatedExtensionHostWorker.disposeIsolatedExtensionHostWorker', getRuntimeId(extensionId, application))]);
|
|
5983
|
+
const results = await Promise.allSettled([disposeExtension(application, extensionId), Promise.try(() => rpc?.dispose()), invoke$2('LaunchIsolatedExtensionHostWorker.disposeIsolatedExtensionHostWorker', getRuntimeId(extensionId, application))]);
|
|
5877
5984
|
assertCurrentApplication(application);
|
|
5878
5985
|
resetExtensionActivation(extensionId, application);
|
|
5879
5986
|
resetExtensionRuntimeState(extensionId, applicationId);
|
|
@@ -5972,10 +6079,10 @@ const invokeForApplication = async (applicationId, method, ...args) => {
|
|
|
5972
6079
|
}
|
|
5973
6080
|
switch (method) {
|
|
5974
6081
|
case 'ExtensionApi.readFile':
|
|
5975
|
-
return invoke('Application.execute', applicationId, 'FileSystem.readFile', ...args);
|
|
6082
|
+
return invoke$2('Application.execute', applicationId, 'FileSystem.readFile', ...args);
|
|
5976
6083
|
case 'ExtensionHostQuickPick.showQuickInput':
|
|
5977
6084
|
case 'ExtensionHostQuickPick.showQuickPick':
|
|
5978
|
-
return invoke('Application.execute', applicationId, method, ...args);
|
|
6085
|
+
return invoke$2('Application.execute', applicationId, method, ...args);
|
|
5979
6086
|
case 'Extensions.activateByEvent':
|
|
5980
6087
|
return activateByEvent(args[0], args[1], args[2] ?? application.platform, application);
|
|
5981
6088
|
case 'Extensions.createWebViewWorkerRpc':
|
|
@@ -6002,7 +6109,7 @@ const invokeForApplication = async (applicationId, method, ...args) => {
|
|
|
6002
6109
|
case 'Extensions.sendMessagePortToFileSystemWorker':
|
|
6003
6110
|
return createFileSystemPort(application, args[0]);
|
|
6004
6111
|
case 'Extensions.showNotification':
|
|
6005
|
-
return invoke('Application.execute', applicationId, 'Notification.create', ...args);
|
|
6112
|
+
return invoke$2('Application.execute', applicationId, 'Notification.create', ...args);
|
|
6006
6113
|
default:
|
|
6007
6114
|
throw new Error(`Extension command does not support application context: ${method}`);
|
|
6008
6115
|
}
|
|
@@ -6029,6 +6136,7 @@ const commandMap = {
|
|
|
6029
6136
|
'Extensions.addWebExtension': addWebExtension,
|
|
6030
6137
|
'Extensions.clearNotifications': clearNotifications,
|
|
6031
6138
|
'Extensions.clearOutputChannel': wrapCommand(clearOutputChannel),
|
|
6139
|
+
'Extensions.connectWorkspaceTerminal': connectTerminal,
|
|
6032
6140
|
'Extensions.createApplication': createApplication,
|
|
6033
6141
|
'Extensions.createViewInstance': createViewInstance,
|
|
6034
6142
|
'Extensions.createWebViewWorkerRpc': createWebViewWorkerRpc,
|
|
@@ -6064,6 +6172,7 @@ const commandMap = {
|
|
|
6064
6172
|
'Extensions.executeResolveCompletionItemProvider': wrapCommand(executeResolveCompletionItemProvider),
|
|
6065
6173
|
'Extensions.executeSignatureHelpProvider': wrapCommand(executeSignatureHelpProvider),
|
|
6066
6174
|
'Extensions.executeSourceControlProvider': wrapCommand(executeSourceControlProvider),
|
|
6175
|
+
'Extensions.executeWorkspaceRequest': request,
|
|
6067
6176
|
'Extensions.getAccessToken': getAccessToken,
|
|
6068
6177
|
'Extensions.getAllExtensions': getAllExtensions,
|
|
6069
6178
|
'Extensions.getColorThemeCss': getColorThemeCss,
|
|
@@ -6089,6 +6198,7 @@ const commandMap = {
|
|
|
6089
6198
|
'Extensions.getViewInstanceState': getViewInstanceState,
|
|
6090
6199
|
'Extensions.getViewMenuEntries': getViewMenuEntries,
|
|
6091
6200
|
'Extensions.getViews': getViews,
|
|
6201
|
+
'Extensions.getWorkspaceTransportUri': getWorkspaceTransportUri,
|
|
6092
6202
|
'Extensions.handleData': handleData,
|
|
6093
6203
|
'Extensions.handleFileChanges': handleFileChanges,
|
|
6094
6204
|
'Extensions.handleLinkedExtensionChange': handleLinkedExtensionChange,
|