ionic-framework: bug: Uncaught RangeError: Maximum call stack size exceeded. Stacked overlays with focusable elements

Prerequisites

Ionic Framework Version

  • v4.x
  • v5.x
  • v6.x

Current Behavior

An Ionic component with an overlay and a focusable element opens another Ionic component with an overlay and a focusable element. Infinite loop occurs (trapkeyboardFocus leads to focus on a descendant, causing focus event handler to spawn the same behaviour):

Uncaught RangeError: Maximum call stack size exceeded.
    at focusElement (helpers-eed79a2b.js:158)
    at focusFirstDescendant (overlays-5f2f4ffc.js:4090)
    at trapShadowFocus (overlays-5f2f4ffc.js:4230)
    at trapKeyboardFocus (overlays-5f2f4ffc.js:4247)
    at HTMLDocument.<anonymous> (overlays-5f2f4ffc.js:4256)
    at ZoneDelegate.invokeTask (zone.js:434)
    at Zone.runTask (zone.js:205)
    at ZoneTask.invokeTask [as invoke] (zone.js:516)
    at invokeTask (zone.js:1656)
    at HTMLDocument.globalZoneAwareCaptureCallback (zone.js:1725)

Expected Behavior

No infinite loop that causes call stack size to be exceeded.

Steps to Reproduce

  1. ionic start Angular project
  2. choose menu template
  3. make menu have an overlay by removing the split pane in the template’s app component’s HTML
  4. create a modal with a button inside of it
  5. make an ion-item as a button in the menu present the modal

Code Reproduction URL

https://github.com/CFT-Chris/trapKeyboardFocusBug

Ionic Info

Ionic:

   Ionic CLI                     : 6.18.1 (/home/chris/.nvm/versions/node/v16.13.1/lib/node_modules/@ionic/cli)
   Ionic Framework               : @ionic/angular 6.0.1
   @angular-devkit/build-angular : 13.0.4
   @angular-devkit/schematics    : 13.0.4
   @angular/cli                  : 13.0.4
   @ionic/angular-toolkit        : 5.0.3

Capacitor:

   Capacitor CLI      : 3.3.3
   @capacitor/android : not installed
   @capacitor/core    : 3.3.3
   @capacitor/ios     : not installed

Utility:

   cordova-res : not installed globally
   native-run  : 1.5.0

System:

   NodeJS : v16.13.1 (/home/chris/.nvm/versions/node/v16.13.1/bin/node)
   npm    : 8.1.2
   OS     : Linux 5.13

Additional Information

This was already logged here but was closed due to inactivity: https://github.com/ionic-team/ionic-framework/issues/23655

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 10
  • Comments: 17 (7 by maintainers)

Most upvoted comments

Same problem, any update?

same problem here any update ?

same problem here

Hello @CFT-Chris thanks for reporting this issue & attaching an example. I’m seeing the same behavior on my end.

Will share more once the team has a moment to prioritize in the upcoming sprints.

Yes, it appears to be working now. Thanks!

Now working without error:

  • opening a popover or modal from a menu (with menu staying open after second overlay presented)
  • focusing on an input element with tab or click in the second overlay
  • first input element doesn’t automatically get focus, which is good for keeping the initial placeholder/hint displayed

Presumably whatever the new behaviour was supposed to be introduced with the new “trapKeyboardFocus”/“focusFirstDescendant” is still there, but I don’t know what to test to confirm that.

I escaped the broken by inserting a first input <input style="display: none;" />

same problem here

An option to turn this behaviour off (focusFirstDescendant) would be preferable in addition to fixing the infinite loop case, since many applications have modal or popover forms and placeholders/hints for unfocused inputs.

If the first form element always gains focus, then any placeholder or hint is never seen. In some cases, validation also triggers prematurely showing an error for that input element. Focusing on the modal/popover itself would be optimal (e.g. with its tabIndex=“-1”) so that accessibility can still focus on the first input with a Tab keypress.