mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-26 11:38:51 +01:00
Merge branch 'main' into rchiodo/celloutputs_update
This commit is contained in:
@@ -3,15 +3,30 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import type * as vscode from 'vscode';
|
||||
import assert = require('assert');
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { mock } from 'vs/base/test/common/mock';
|
||||
import { IEditorTabDto, MainThreadEditorTabsShape, TabKind } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostEditorTabs, IEditorTabGroup } from 'vs/workbench/api/common/extHostEditorTabs';
|
||||
import { IEditorTabDto, MainThreadEditorTabsShape, TabInputKind, TextInputDto } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostEditorTabs } from 'vs/workbench/api/common/extHostEditorTabs';
|
||||
import { SingleProxyRPCProtocol } from 'vs/workbench/api/test/common/testRPCProtocol';
|
||||
import { TextTabInput } from 'vs/workbench/api/common/extHostTypes';
|
||||
|
||||
suite('ExtHostEditorTabs', function () {
|
||||
|
||||
const defaultTabDto: IEditorTabDto = {
|
||||
id: 'uniquestring',
|
||||
input: { kind: TabInputKind.TextInput, uri: URI.parse('file://abc/def.txt') },
|
||||
isActive: true,
|
||||
isDirty: true,
|
||||
isPinned: true,
|
||||
isPreview: false,
|
||||
label: 'label1',
|
||||
};
|
||||
|
||||
function createTabDto(dto?: Partial<IEditorTabDto>): IEditorTabDto {
|
||||
return { ...defaultTabDto, ...dto };
|
||||
}
|
||||
|
||||
test('empty', function () {
|
||||
|
||||
@@ -21,7 +36,7 @@ suite('ExtHostEditorTabs', function () {
|
||||
})
|
||||
);
|
||||
|
||||
assert.strictEqual(extHostEditorTabs.tabGroups.all.length, 0);
|
||||
assert.strictEqual(extHostEditorTabs.tabGroups.groups.length, 0);
|
||||
assert.strictEqual(extHostEditorTabs.tabGroups.activeTabGroup, undefined);
|
||||
});
|
||||
|
||||
@@ -33,25 +48,22 @@ suite('ExtHostEditorTabs', function () {
|
||||
})
|
||||
);
|
||||
|
||||
const tab: IEditorTabDto = {
|
||||
const tab: IEditorTabDto = createTabDto({
|
||||
id: 'uniquestring',
|
||||
isActive: true,
|
||||
isDirty: true,
|
||||
isPinned: true,
|
||||
label: 'label1',
|
||||
viewColumn: 0,
|
||||
additionalResourcesAndViewTypes: [],
|
||||
kind: TabKind.Other
|
||||
};
|
||||
});
|
||||
|
||||
extHostEditorTabs.$acceptEditorTabModel([{
|
||||
isActive: true,
|
||||
viewColumn: 0,
|
||||
groupId: 12,
|
||||
tabs: [tab],
|
||||
activeTab: { ...tab }
|
||||
tabs: [tab]
|
||||
}]);
|
||||
assert.strictEqual(extHostEditorTabs.tabGroups.all.length, 1);
|
||||
const [first] = extHostEditorTabs.tabGroups.all;
|
||||
assert.strictEqual(extHostEditorTabs.tabGroups.groups.length, 1);
|
||||
const [first] = extHostEditorTabs.tabGroups.groups;
|
||||
assert.ok(first.activeTab);
|
||||
assert.strictEqual(first.tabs.indexOf(first.activeTab), 0);
|
||||
|
||||
@@ -60,11 +72,10 @@ suite('ExtHostEditorTabs', function () {
|
||||
isActive: true,
|
||||
viewColumn: 0,
|
||||
groupId: 12,
|
||||
tabs: [tab],
|
||||
activeTab: undefined! // TODO@lramos15 unused
|
||||
tabs: [tab]
|
||||
}]);
|
||||
assert.strictEqual(extHostEditorTabs.tabGroups.all.length, 1);
|
||||
const [first] = extHostEditorTabs.tabGroups.all;
|
||||
assert.strictEqual(extHostEditorTabs.tabGroups.groups.length, 1);
|
||||
const [first] = extHostEditorTabs.tabGroups.groups;
|
||||
assert.ok(first.activeTab);
|
||||
assert.strictEqual(first.tabs.indexOf(first.activeTab), 0);
|
||||
}
|
||||
@@ -81,11 +92,10 @@ suite('ExtHostEditorTabs', function () {
|
||||
isActive: true,
|
||||
viewColumn: 0,
|
||||
groupId: 12,
|
||||
tabs: [],
|
||||
activeTab: undefined
|
||||
tabs: []
|
||||
}]);
|
||||
assert.strictEqual(extHostEditorTabs.tabGroups.all.length, 1);
|
||||
const [first] = extHostEditorTabs.tabGroups.all;
|
||||
assert.strictEqual(extHostEditorTabs.tabGroups.groups.length, 1);
|
||||
const [first] = extHostEditorTabs.tabGroups.groups;
|
||||
assert.strictEqual(first.activeTab, undefined);
|
||||
assert.strictEqual(first.tabs.length, 0);
|
||||
});
|
||||
@@ -101,19 +111,18 @@ suite('ExtHostEditorTabs', function () {
|
||||
extHostEditorTabs.tabGroups.onDidChangeTabGroup(() => count++);
|
||||
|
||||
|
||||
assert.strictEqual(extHostEditorTabs.tabGroups.all.length, 0);
|
||||
assert.strictEqual(extHostEditorTabs.tabGroups.groups.length, 0);
|
||||
assert.strictEqual(extHostEditorTabs.tabGroups.activeTabGroup, undefined);
|
||||
assert.strictEqual(count, 0);
|
||||
extHostEditorTabs.$acceptEditorTabModel([{
|
||||
isActive: true,
|
||||
viewColumn: 0,
|
||||
groupId: 12,
|
||||
tabs: [],
|
||||
activeTab: undefined
|
||||
tabs: []
|
||||
}]);
|
||||
assert.ok(extHostEditorTabs.tabGroups.activeTabGroup);
|
||||
const activeTabGroup: IEditorTabGroup = extHostEditorTabs.tabGroups.activeTabGroup;
|
||||
assert.strictEqual(extHostEditorTabs.tabGroups.all.length, 1);
|
||||
const activeTabGroup: vscode.TabGroup = extHostEditorTabs.tabGroups.activeTabGroup;
|
||||
assert.strictEqual(extHostEditorTabs.tabGroups.groups.length, 1);
|
||||
assert.strictEqual(activeTabGroup.tabs.length, 0);
|
||||
assert.strictEqual(count, 1);
|
||||
});
|
||||
@@ -124,34 +133,31 @@ suite('ExtHostEditorTabs', function () {
|
||||
// override/implement $moveTab or $closeTab
|
||||
})
|
||||
);
|
||||
const tab: IEditorTabDto = {
|
||||
const tab = createTabDto({
|
||||
id: 'uniquestring',
|
||||
isActive: true,
|
||||
isDirty: true,
|
||||
isPinned: true,
|
||||
label: 'label1',
|
||||
resource: URI.parse('file://abc/def.txt'),
|
||||
editorId: 'default',
|
||||
viewColumn: 0,
|
||||
additionalResourcesAndViewTypes: [],
|
||||
kind: TabKind.Singular
|
||||
};
|
||||
});
|
||||
|
||||
extHostEditorTabs.$acceptEditorTabModel([{
|
||||
isActive: true,
|
||||
viewColumn: 0,
|
||||
groupId: 12,
|
||||
tabs: [tab],
|
||||
activeTab: { ...tab }
|
||||
tabs: [tab]
|
||||
}]);
|
||||
assert.strictEqual(extHostEditorTabs.tabGroups.all.length, 1);
|
||||
const [first] = extHostEditorTabs.tabGroups.all;
|
||||
assert.strictEqual(extHostEditorTabs.tabGroups.groups.length, 1);
|
||||
const [first] = extHostEditorTabs.tabGroups.groups;
|
||||
assert.ok(first.activeTab);
|
||||
assert.strictEqual(first.tabs.indexOf(first.activeTab), 0);
|
||||
assert.strictEqual(first.activeTab, first.tabs[0]);
|
||||
assert.strictEqual(extHostEditorTabs.tabGroups.activeTabGroup, first);
|
||||
});
|
||||
|
||||
test('onDidChangeActiveTabGroup fires properly', function () {
|
||||
// TODO @lramos15 Change this test because now it only fires when id changes
|
||||
test.skip('onDidChangeActiveTabGroup fires properly', function () {
|
||||
const extHostEditorTabs = new ExtHostEditorTabs(
|
||||
SingleProxyRPCProtocol(new class extends mock<MainThreadEditorTabsShape>() {
|
||||
// override/implement $moveTab or $closeTab
|
||||
@@ -159,14 +165,14 @@ suite('ExtHostEditorTabs', function () {
|
||||
);
|
||||
|
||||
let count = 0;
|
||||
let activeTabGroupFromEvent: IEditorTabGroup | undefined = undefined;
|
||||
let activeTabGroupFromEvent: vscode.TabGroup | undefined = undefined;
|
||||
extHostEditorTabs.tabGroups.onDidChangeActiveTabGroup((tabGroup) => {
|
||||
count++;
|
||||
activeTabGroupFromEvent = tabGroup;
|
||||
});
|
||||
|
||||
|
||||
assert.strictEqual(extHostEditorTabs.tabGroups.all.length, 0);
|
||||
assert.strictEqual(extHostEditorTabs.tabGroups.groups.length, 0);
|
||||
assert.strictEqual(extHostEditorTabs.tabGroups.activeTabGroup, undefined);
|
||||
assert.strictEqual(count, 0);
|
||||
const tabModel = [{
|
||||
@@ -178,7 +184,7 @@ suite('ExtHostEditorTabs', function () {
|
||||
}];
|
||||
extHostEditorTabs.$acceptEditorTabModel(tabModel);
|
||||
assert.ok(extHostEditorTabs.tabGroups.activeTabGroup);
|
||||
let activeTabGroup: IEditorTabGroup = extHostEditorTabs.tabGroups.activeTabGroup;
|
||||
let activeTabGroup: vscode.TabGroup = extHostEditorTabs.tabGroups.activeTabGroup;
|
||||
assert.strictEqual(count, 1);
|
||||
assert.strictEqual(activeTabGroup, activeTabGroupFromEvent);
|
||||
// Firing again with same model shouldn't cause a change
|
||||
@@ -212,24 +218,14 @@ suite('ExtHostEditorTabs', function () {
|
||||
assert.strictEqual(activeTabGroup, activeTabGroupFromEvent);
|
||||
});
|
||||
|
||||
test.skip('Ensure reference stability', function () {
|
||||
test('Ensure reference stability', function () {
|
||||
|
||||
const extHostEditorTabs = new ExtHostEditorTabs(
|
||||
SingleProxyRPCProtocol(new class extends mock<MainThreadEditorTabsShape>() {
|
||||
// override/implement $moveTab or $closeTab
|
||||
})
|
||||
);
|
||||
const tabDto: IEditorTabDto = {
|
||||
isActive: true,
|
||||
isDirty: true,
|
||||
isPinned: true,
|
||||
label: 'label1',
|
||||
resource: URI.parse('file://abc/def.txt'),
|
||||
editorId: 'default',
|
||||
viewColumn: 0,
|
||||
additionalResourcesAndViewTypes: [],
|
||||
kind: TabKind.Singular
|
||||
};
|
||||
const tabDto = createTabDto();
|
||||
|
||||
// single dirty tab
|
||||
|
||||
@@ -237,33 +233,193 @@ suite('ExtHostEditorTabs', function () {
|
||||
isActive: true,
|
||||
viewColumn: 0,
|
||||
groupId: 12,
|
||||
tabs: [tabDto],
|
||||
activeTab: undefined // NOT needed
|
||||
tabs: [tabDto]
|
||||
}]);
|
||||
let all = extHostEditorTabs.tabGroups.all.map(group => group.tabs).flat();
|
||||
let all = extHostEditorTabs.tabGroups.groups.map(group => group.tabs).flat();
|
||||
assert.strictEqual(all.length, 1);
|
||||
const apiTab1 = all[0];
|
||||
assert.strictEqual(apiTab1.resource?.toString(), URI.revive(tabDto.resource)?.toString());
|
||||
assert.ok(apiTab1.input instanceof TextTabInput);
|
||||
assert.strictEqual(tabDto.input.kind, TabInputKind.TextInput);
|
||||
const dtoResource = (tabDto.input as TextInputDto).uri;
|
||||
assert.strictEqual(apiTab1.input.uri.toString(), URI.revive(dtoResource).toString());
|
||||
assert.strictEqual(apiTab1.isDirty, true);
|
||||
|
||||
|
||||
// NOT DIRTY anymore
|
||||
|
||||
const tabDto2: IEditorTabDto = { ...tabDto, isDirty: false };
|
||||
extHostEditorTabs.$acceptEditorTabModel([{
|
||||
isActive: true,
|
||||
viewColumn: 0,
|
||||
groupId: 12,
|
||||
tabs: [tabDto2],
|
||||
activeTab: undefined // NOT needed
|
||||
}]);
|
||||
// Accept a simple update
|
||||
extHostEditorTabs.$acceptTabUpdate(12, tabDto2);
|
||||
|
||||
all = extHostEditorTabs.tabGroups.all.map(group => group.tabs).flat();
|
||||
all = extHostEditorTabs.tabGroups.groups.map(group => group.tabs).flat();
|
||||
assert.strictEqual(all.length, 1);
|
||||
const apiTab2 = all[0];
|
||||
assert.strictEqual(apiTab2.resource?.toString(), URI.revive(tabDto.resource)?.toString());
|
||||
assert.ok(apiTab1.input instanceof TextTabInput);
|
||||
assert.strictEqual(apiTab1.input.uri.toString(), URI.revive(dtoResource).toString());
|
||||
assert.strictEqual(apiTab2.isDirty, false);
|
||||
|
||||
assert.strictEqual(apiTab1 === apiTab2, true);
|
||||
});
|
||||
|
||||
test('Tab.isActive working', function () {
|
||||
|
||||
const extHostEditorTabs = new ExtHostEditorTabs(
|
||||
SingleProxyRPCProtocol(new class extends mock<MainThreadEditorTabsShape>() {
|
||||
// override/implement $moveTab or $closeTab
|
||||
})
|
||||
);
|
||||
const tabDtoAAA = createTabDto({
|
||||
id: 'AAA',
|
||||
isActive: true,
|
||||
isDirty: true,
|
||||
isPinned: true,
|
||||
label: 'label1',
|
||||
input: { kind: TabInputKind.TextInput, uri: URI.parse('file://abc/AAA.txt') },
|
||||
editorId: 'default'
|
||||
});
|
||||
|
||||
const tabDtoBBB = createTabDto({
|
||||
id: 'BBB',
|
||||
isActive: false,
|
||||
isDirty: true,
|
||||
isPinned: true,
|
||||
label: 'label1',
|
||||
input: { kind: TabInputKind.TextInput, uri: URI.parse('file://abc/BBB.txt') },
|
||||
editorId: 'default'
|
||||
});
|
||||
|
||||
// single dirty tab
|
||||
|
||||
extHostEditorTabs.$acceptEditorTabModel([{
|
||||
isActive: true,
|
||||
viewColumn: 0,
|
||||
groupId: 12,
|
||||
tabs: [tabDtoAAA, tabDtoBBB]
|
||||
}]);
|
||||
|
||||
let all = extHostEditorTabs.tabGroups.groups.map(group => group.tabs).flat();
|
||||
assert.strictEqual(all.length, 2);
|
||||
|
||||
const activeTab1 = extHostEditorTabs.tabGroups.activeTabGroup?.activeTab;
|
||||
assert.ok(activeTab1?.input instanceof TextTabInput);
|
||||
assert.strictEqual(tabDtoAAA.input.kind, TabInputKind.TextInput);
|
||||
const dtoAAAResource = (tabDtoAAA.input as TextInputDto).uri;
|
||||
assert.strictEqual(activeTab1?.input?.uri.toString(), URI.revive(dtoAAAResource)?.toString());
|
||||
assert.strictEqual(activeTab1?.isActive, true);
|
||||
|
||||
extHostEditorTabs.$acceptTabUpdate(12, { ...tabDtoBBB, isActive: true }); /// BBB is now active
|
||||
|
||||
const activeTab2 = extHostEditorTabs.tabGroups.activeTabGroup?.activeTab;
|
||||
assert.ok(activeTab2?.input instanceof TextTabInput);
|
||||
assert.strictEqual(tabDtoBBB.input.kind, TabInputKind.TextInput);
|
||||
const dtoBBBResource = (tabDtoBBB.input as TextInputDto).uri;
|
||||
assert.strictEqual(activeTab2?.input?.uri.toString(), URI.revive(dtoBBBResource)?.toString());
|
||||
assert.strictEqual(activeTab2?.isActive, true);
|
||||
assert.strictEqual(activeTab1?.isActive, false);
|
||||
});
|
||||
|
||||
test('vscode.window.tagGroups is immutable', function () {
|
||||
|
||||
const extHostEditorTabs = new ExtHostEditorTabs(
|
||||
SingleProxyRPCProtocol(new class extends mock<MainThreadEditorTabsShape>() {
|
||||
// override/implement $moveTab or $closeTab
|
||||
})
|
||||
);
|
||||
|
||||
assert.throws(() => {
|
||||
// @ts-expect-error write to readonly prop
|
||||
extHostEditorTabs.tabGroups.activeTabGroup = undefined;
|
||||
});
|
||||
assert.throws(() => {
|
||||
// @ts-expect-error write to readonly prop
|
||||
extHostEditorTabs.tabGroups.groups.length = 0;
|
||||
});
|
||||
assert.throws(() => {
|
||||
// @ts-expect-error write to readonly prop
|
||||
extHostEditorTabs.tabGroups.onDidChangeActiveTabGroup = undefined;
|
||||
});
|
||||
assert.throws(() => {
|
||||
// @ts-expect-error write to readonly prop
|
||||
extHostEditorTabs.tabGroups.onDidChangeTabGroup = undefined;
|
||||
});
|
||||
});
|
||||
|
||||
test('Ensure close is called with all tab ids', function () {
|
||||
let closedTabIds: string[][] = [];
|
||||
const extHostEditorTabs = new ExtHostEditorTabs(
|
||||
SingleProxyRPCProtocol(new class extends mock<MainThreadEditorTabsShape>() {
|
||||
// override/implement $moveTab or $closeTab
|
||||
override async $closeTab(tabIds: string[], preserveFocus?: boolean) {
|
||||
closedTabIds.push(tabIds);
|
||||
}
|
||||
})
|
||||
);
|
||||
const tab: IEditorTabDto = createTabDto({
|
||||
id: 'uniquestring',
|
||||
isActive: true,
|
||||
isDirty: true,
|
||||
isPinned: true,
|
||||
label: 'label1',
|
||||
editorId: 'default'
|
||||
});
|
||||
|
||||
extHostEditorTabs.$acceptEditorTabModel([{
|
||||
isActive: true,
|
||||
viewColumn: 0,
|
||||
groupId: 12,
|
||||
tabs: [tab]
|
||||
}]);
|
||||
assert.strictEqual(extHostEditorTabs.tabGroups.groups.length, 1);
|
||||
const activeTab = extHostEditorTabs.tabGroups.activeTabGroup?.activeTab;
|
||||
assert.ok(activeTab);
|
||||
extHostEditorTabs.tabGroups.close(activeTab, false);
|
||||
assert.strictEqual(closedTabIds.length, 1);
|
||||
assert.deepStrictEqual(closedTabIds[0], ['uniquestring']);
|
||||
// Close with array
|
||||
extHostEditorTabs.tabGroups.close([activeTab], false);
|
||||
assert.strictEqual(closedTabIds.length, 2);
|
||||
assert.deepStrictEqual(closedTabIds[1], ['uniquestring']);
|
||||
});
|
||||
|
||||
test('Update tab only sends tab change event', async function () {
|
||||
let closedTabIds: string[][] = [];
|
||||
const extHostEditorTabs = new ExtHostEditorTabs(
|
||||
SingleProxyRPCProtocol(new class extends mock<MainThreadEditorTabsShape>() {
|
||||
// override/implement $moveTab or $closeTab
|
||||
override async $closeTab(tabIds: string[], preserveFocus?: boolean) {
|
||||
closedTabIds.push(tabIds);
|
||||
}
|
||||
})
|
||||
);
|
||||
const tabDto: IEditorTabDto = createTabDto({
|
||||
id: 'uniquestring',
|
||||
isActive: true,
|
||||
isDirty: true,
|
||||
isPinned: true,
|
||||
label: 'label1',
|
||||
editorId: 'default'
|
||||
});
|
||||
|
||||
extHostEditorTabs.$acceptEditorTabModel([{
|
||||
isActive: true,
|
||||
viewColumn: 0,
|
||||
groupId: 12,
|
||||
tabs: [tabDto]
|
||||
}]);
|
||||
|
||||
assert.strictEqual(extHostEditorTabs.tabGroups.groups.length, 1);
|
||||
assert.strictEqual(extHostEditorTabs.tabGroups.groups.map(g => g.tabs).flat().length, 1);
|
||||
|
||||
const tab = extHostEditorTabs.tabGroups.groups[0].tabs[0];
|
||||
|
||||
const p = new Promise<vscode.Tab>(resolve => extHostEditorTabs.tabGroups.onDidChangeTab(resolve));
|
||||
|
||||
extHostEditorTabs.$acceptTabUpdate(12, { ...tabDto, label: 'NEW LABEL' });
|
||||
|
||||
const changedTab = await p;
|
||||
|
||||
assert.ok(tab === changedTab);
|
||||
assert.strictEqual(changedTab.label, 'NEW LABEL');
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -32,7 +32,7 @@ suite('ExtHostWebview', () => {
|
||||
test('Cannot register multiple serializers for the same view type', async () => {
|
||||
const viewType = 'view.type';
|
||||
|
||||
const extHostWebviews = new ExtHostWebviews(rpcProtocol!, { remote: { authority: undefined, isRemote: false } }, undefined, new NullLogService(), NullApiDeprecationService);
|
||||
const extHostWebviews = new ExtHostWebviews(rpcProtocol!, { authority: undefined, isRemote: false }, undefined, new NullLogService(), NullApiDeprecationService);
|
||||
|
||||
const extHostWebviewPanels = new ExtHostWebviewPanels(rpcProtocol!, extHostWebviews, undefined);
|
||||
|
||||
@@ -169,10 +169,8 @@ suite('ExtHostWebview', () => {
|
||||
|
||||
function createWebview(rpcProtocol: (IExtHostRpcService & IExtHostContext) | undefined, remoteAuthority: string | undefined) {
|
||||
const extHostWebviews = new ExtHostWebviews(rpcProtocol!, {
|
||||
remote: {
|
||||
authority: remoteAuthority,
|
||||
isRemote: !!remoteAuthority,
|
||||
},
|
||||
authority: remoteAuthority,
|
||||
isRemote: !!remoteAuthority,
|
||||
}, undefined, new NullLogService(), NullApiDeprecationService);
|
||||
|
||||
const extHostWebviewPanels = new ExtHostWebviewPanels(rpcProtocol!, extHostWebviews, undefined);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import * as assert from 'assert';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { ExtensionIdentifier, IExtensionDescription, TargetPlatform } from 'vs/platform/extensions/common/extensions';
|
||||
import { NullLogService } from 'vs/platform/log/common/log';
|
||||
import { ActivatedExtension, EmptyExtension, ExtensionActivationTimes, ExtensionsActivator, IExtensionsActivatorHost } from 'vs/workbench/api/common/extHostExtensionActivator';
|
||||
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry';
|
||||
@@ -261,6 +261,7 @@ suite('ExtensionsActivator', () => {
|
||||
isUserBuiltin: false,
|
||||
activationEvents,
|
||||
main: 'index.js',
|
||||
targetPlatform: TargetPlatform.UNDEFINED,
|
||||
extensionDependencies: deps.map(d => d.value)
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user