ng-bootstrap / ng-bootstrap

Angular powered Bootstrap

Home Page:https://ng-bootstrap.github.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

NgTypeAhead: Duplicate list entries causing browser tab freeze

RobinRSC opened this issue · comments

Bug description:

When ngbTypeahead directive is used to filter lists with approx. 130 items or more, the browser tab simply hangs and crashes on some inputs like "ee".

Steps to reproduce

  • Open attached StackBlitz (the code is based on the official example from the docs with adjusted list items)
  • type in "ee" in the input field
Expected Result

The autocompletion list is filtered and shows no suggestion as there is no option matching the input "ee"

Actual Result

  • According to monitor tab of Chrome, the cpu load spikes to 100%, memory consumption keeps on growing
  • Eventually the browser tab/StackBlitz page hangs, sometimes even crashes

Link to minimally-working StackBlitz that reproduces the issue:

https://stackblitz.com/edit/angular-2cd1vg?file=src%2Fapp%2Ftypeahead-focus.html

Versions of Angular, ng-bootstrap and Bootstrap:

Angular: 17.3.9

ng-bootstrap: 16.0.0

Bootstrap: 5.3.3

After a lot of debugging work, I finally found the following assertion being triggered:

grafik

Unfortunately the assertion message can only be found when debugging the library code.

It also seems like the lib hangs in an infinite recursion after the assertion was thrown causing the browser tab to freeze/crash

I guess this must be related to #4705

@maxokorokov I don't think so. I rather think that it's caused by a duplicate option "Acromion" in the stackblitz, and this line in the code: https://github.com/ng-bootstrap/ng-bootstrap/blob/master/src/typeahead/typeahead-window.ts#L43.

It's trickier here because

  • to me, it's kind of a user-code bug to have duplicate options
  • there is no real correct track expression here. Ideally, the options would be objects with a unique identifier and we would track by this identifier, but this is of course not possible.

I think we should track by index. It might be less ideal than tracking by identity in most cases, but the list should be small and the DOM elements to drop and update are minimal (since it's a typeahead). And at least it should be safe and wouldn't emit warnings if there are duplicates in the list.