Skip to content

bug(selection-model): SelectionModel.setSelection() throws RangeError on large arrays (spreads values as call args) #33466

Description

@t00

Is this a regression?

  • Yes, this behavior used to work in the previous version

The previous version in which this bug was not present was

No response

Description

SelectionModel.setSelection(...values: T[]) is the only public API for replacing the whole selection in one call, but its rest-parameter signature means the caller must spread the array into the call. For large selections this exceeds the JavaScript engine's function-argument limit and throws:

RangeError: Maximum call stack size exceeded

There is no array-accepting alternative, so a "select all" over a large list (e.g. a virtual-scroll grid of 100k+ rows) has no working public path: setSelection(...all) crashes, and the per-item select() loop is O(n²) when a compareWith is configured (each _getConcreteValue linearly scans the growing set). This effectively makes bulk selection of large lists impossible without reaching into the private _selection field.

Additional context:

Reproduction

Steps: run the snippet (StackBlitz or node). The exact threshold is engine-dependent (Chrome/V8 throws well before Node does), so increase N if it doesn't trip immediately.

StackBlitz

import { SelectionModel } from '@angular/cdk/collections';

const N = 2_000_000; // raise if your engine tolerates this count
const items = Array.from({ length: N }, (_, i) => i);
const model = new SelectionModel<number>(true);

// Works (but O(n²) when a compareWith is supplied):
items.forEach(i => model.select(i));
console.log('incremental select ok:', model.selected.length);
model.clear();

// The only public *bulk* API — throws on large arrays:
model.setSelection(...items); // RangeError: Maximum call stack size exceeded
console.log('setSelection ok:', model.selected.length); // never reached

Expected Behavior

Replacing the selection with a large array should succeed (or at least not crash). Either:

  • setSelection iterates internally instead of spreading, or
  • an array-accepting overload/method is provided, e.g. setSelection(values: T[]) / replaceSelection(values: readonly T[]).

Actual Behavior

setSelection(...largeArray) throws RangeError: Maximum call stack size exceeded. There is no non-crashing public way to bulk-replace a large selection.

Environment

  • @angular/cdk: 20.2.x (signature unchanged on main)
  • Browser: Chrome (V8)

Metadata

Metadata

Assignees

Labels

P3An issue that is relevant to core functions, but does not impede progress. Important, but not urgentarea: cdk/collectionsgemini-triagedLabel noting that an issue has been triaged by gemini

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions