diff --git a/src/vs/base/browser/ui/tree/asyncDataTree.ts b/src/vs/base/browser/ui/tree/asyncDataTree.ts index 39470b6e11b..e1f948802e3 100644 --- a/src/vs/base/browser/ui/tree/asyncDataTree.ts +++ b/src/vs/base/browser/ui/tree/asyncDataTree.ts @@ -313,7 +313,7 @@ export class AsyncDataTree implements IDisposable private readonly collapseByDefault?: { (e: T): boolean; }; private readonly subTreeRefreshPromises = new Map, Promise>(); - private readonly refreshPromises = new Map, CancelablePromise>(); + private readonly refreshPromises = new Map, CancelablePromise>>(); protected readonly identityProvider?: IIdentityProvider; private readonly autoExpandSingleChildren: boolean; @@ -740,10 +740,10 @@ export class AsyncDataTree implements IDisposable private async doRefreshNode(node: IAsyncDataTreeNode, recursive: boolean, viewStateContext?: IAsyncDataTreeViewStateContext): Promise[]> { node.hasChildren = !!this.dataSource.hasChildren(node.element!); - let childrenPromise: Promise; + let childrenPromise: Promise>; if (!node.hasChildren) { - childrenPromise = Promise.resolve([]); + childrenPromise = Promise.resolve(Iterable.empty()); } else { const slowTimeout = timeout(800); @@ -777,7 +777,7 @@ export class AsyncDataTree implements IDisposable } } - private doGetChildren(node: IAsyncDataTreeNode): Promise { + private doGetChildren(node: IAsyncDataTreeNode): Promise> { let result = this.refreshPromises.get(node); if (result) { @@ -809,7 +809,9 @@ export class AsyncDataTree implements IDisposable } } - private setChildren(node: IAsyncDataTreeNode, childrenElements: T[], recursive: boolean, viewStateContext?: IAsyncDataTreeViewStateContext): IAsyncDataTreeNode[] { + private setChildren(node: IAsyncDataTreeNode, childrenElementsIterable: Iterable, recursive: boolean, viewStateContext?: IAsyncDataTreeViewStateContext): IAsyncDataTreeNode[] { + const childrenElements = [...childrenElementsIterable]; + // perf: if the node was and still is a leaf, avoid all this hassle if (node.children.length === 0 && childrenElements.length === 0) { return []; @@ -949,9 +951,9 @@ export class AsyncDataTree implements IDisposable }; } - protected processChildren(children: T[]): T[] { + protected processChildren(children: Iterable): Iterable { if (this.sorter) { - children.sort(this.sorter.compare.bind(this.sorter)); + children = [...children].sort(this.sorter.compare.bind(this.sorter)); } return children; @@ -1243,9 +1245,9 @@ export class CompressibleAsyncDataTree extends As // For compressed async data trees, `TreeVisibility.Recurse` doesn't currently work // and we have to filter everything beforehand // Related to #85193 and #85835 - protected processChildren(children: T[]): T[] { + protected processChildren(children: Iterable): Iterable { if (this.filter) { - children = children.filter(e => { + children = Iterable.filter(children, e => { const result = this.filter!.filter(e, TreeVisibility.Visible); const visibility = getVisibility(result); diff --git a/src/vs/base/browser/ui/tree/dataTree.ts b/src/vs/base/browser/ui/tree/dataTree.ts index 34b03c65c26..cf7e1110e95 100644 --- a/src/vs/base/browser/ui/tree/dataTree.ts +++ b/src/vs/base/browser/ui/tree/dataTree.ts @@ -159,7 +159,7 @@ export class DataTree extends AbstractTree boolean | undefined): { elements: Iterable>, size: number } { - const children = this.dataSource.getChildren(element); + const children = [...this.dataSource.getChildren(element)]; const elements = Iterable.map(children, element => { const { elements: children, size } = this.iterate(element, isCollapsed); const collapsible = this.dataSource.hasChildren ? this.dataSource.hasChildren(element) : undefined; diff --git a/src/vs/base/browser/ui/tree/tree.ts b/src/vs/base/browser/ui/tree/tree.ts index ca65afa52a8..085bb3d90b7 100644 --- a/src/vs/base/browser/ui/tree/tree.ts +++ b/src/vs/base/browser/ui/tree/tree.ts @@ -166,12 +166,12 @@ export interface ITreeNavigator { export interface IDataSource { hasChildren?(element: TInput | T): boolean; - getChildren(element: TInput | T): T[]; + getChildren(element: TInput | T): Iterable; } export interface IAsyncDataSource { hasChildren(element: TInput | T): boolean; - getChildren(element: TInput | T): T[] | Promise; + getChildren(element: TInput | T): Iterable | Promise>; } export const enum TreeDragOverBubble {