diff --git a/packages/core/src/browser/tree/tree-iterator.ts b/packages/core/src/browser/tree/tree-iterator.ts index b09b4099521d7..fcc6074fee2f6 100644 --- a/packages/core/src/browser/tree/tree-iterator.ts +++ b/packages/core/src/browser/tree/tree-iterator.ts @@ -202,12 +202,12 @@ export namespace Iterators { * Generator for depth first, pre-order tree traversal iteration. */ export function* depthFirst(root: T, children: (node: T) => T[] | undefined, include: (node: T) => boolean = () => true): IterableIterator { - const stack: T[] = []; + let stack: T[] = []; stack.push(root); while (stack.length > 0) { const top = stack.pop()!; yield top; - stack.push(...(children(top) || []).filter(include).reverse()); + stack = stack.concat((children(top) || []).filter(include).reverse()); } } @@ -215,12 +215,12 @@ export namespace Iterators { * Generator for breadth first tree traversal iteration. */ export function* breadthFirst(root: T, children: (node: T) => T[] | undefined, include: (node: T) => boolean = () => true): IterableIterator { - const queue: T[] = []; + let queue: T[] = []; queue.push(root); while (queue.length > 0) { const head = queue.shift()!; yield head; - queue.push(...(children(head) || []).filter(include)); + queue = queue.concat((children(head) || []).filter(include)); } } diff --git a/packages/core/src/browser/tree/tree-selection-state.spec.ts b/packages/core/src/browser/tree/tree-selection-state.spec.ts index 52ae927602433..cc82c6c9110c6 100644 --- a/packages/core/src/browser/tree/tree-selection-state.spec.ts +++ b/packages/core/src/browser/tree/tree-selection-state.spec.ts @@ -16,10 +16,10 @@ import { expect } from 'chai'; import { MockTreeModel } from './test/mock-tree-model'; -import { TreeSelectionState } from './tree-selection-state'; import { createTreeTestContainer } from './test/tree-test-container'; -import { SelectableTreeNode, TreeSelection } from './tree-selection'; import { TreeModel } from './tree-model'; +import { SelectableTreeNode, TreeSelection } from './tree-selection'; +import { TreeSelectionState } from './tree-selection-state'; namespace TreeSelectionState { @@ -34,6 +34,16 @@ namespace TreeSelectionState { } +const LARGE_FLAT_MOCK_ROOT = (length = 250000) => { + const children = Array.from({ length }, (_, idx) => ({ 'id': (idx + 1).toString() })); + return MockTreeModel.Node.toTreeNode({ + 'id': 'ROOT', + 'children': [ + ...children + ] + }); +}; + describe('tree-selection-state', () => { const model = createTreeModel(); @@ -391,6 +401,23 @@ describe('tree-selection-state', () => { }); }); + it('should be able to handle range selection on large tree', () => { + model.root = LARGE_FLAT_MOCK_ROOT(); + expect(model.selectedNodes).to.be.empty; + + const start = 10; + const end = 20; + newState() + .nextState('toggle', start.toString(), { + focus: start.toString(), + selection: [start.toString()] + }) + .nextState('range', end.toString(), { + focus: start.toString(), + selection: Array.from({ length: end - start + 1 }, (_, idx) => (start + idx).toString()) + }); + }); + function newState(): TreeSelectionState.Assert { return nextState(new TreeSelectionState(model)); }