Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix backdrop "Cannot read property 'removeChild' of null" when removed from body #34014

Merged
merged 1 commit into from
May 21, 2021

Conversation

weaverryan
Copy link
Contributor

Hi!

This fixes #33946

Here is a reproducer: https://weaverryan.github.io/bootstrap-modal-close-reproducer/
Code: https://github.com/weaverryan/bootstrap-modal-close-reproducer/blob/main/index.html#L34-L46

  1. Click "Launch demo modal"
  2. Click "Save changes" in the modal.

Then in the console you'll see:

TypeError: Cannot read property 'removeChild' of null
(backdrop.js:119)

This occurs if you hide() a backdrop, but then the HTML of the backdrop is removed from the body while its animation is finishing. From the reproducer:

bootstrap.Modal.getInstance(document.querySelector('#exampleModal')).hide();
document.body.innerHTML = 'Page content changed';

When would this happen? It happens, for example, if you're using Turbo. For example, if you close a modal, then immediately "visit" another page, in reality, that just swaps the body.innerHTML for the page, which causes backdrop to error when it can't find its parent (after the animation).

Please let me know if you need any more clarification or tweaks to the PR :).

Thanks!

@weaverryan weaverryan requested a review from a team as a code owner May 17, 2021 18:43
document.body.innerHTML = 'changed';
})
})

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI - without the fix, this test causes this failure:

Chrome Headless 90.0.4430.212 (Mac OS 10.15.7) Backdrop should not error if the backdrop no longer has a parent FAILED
	Uncaught TypeError: Cannot read property 'removeChild' of null thrown

@alpadev alpadev requested a review from GeoSot May 18, 2021 19:54
@GeoSot
Copy link
Member

GeoSot commented May 18, 2021

/CC @alpadev @rohit2sharma95

this is similar to #33727. We have the asynchronous process error

The script that triggers that causes the problem, deletes everything without wait for transitionend

document.querySelector('#save-changes').addEventListener('click', (event) => {
      bootstrap.Modal.getInstance(document.querySelector('#exampleModal')).hide(); // THIS IS AN ASYNC PROCESS
      document.body.innerHTML = 'Page content changed (e.g. faking an AJAX navigation). Check the console for the error.'; //THIS remove everything (plus parentElement) synchronously 
  });

Proposal: as alert, tooltip, backdrop, use the same process and checks, isn't safer to extract the functionality to utils or to Manipulator.remove() instead to make inline checks?

@weaverryan
Copy link
Contributor Author

Proposal: as alert, tooltip, backdrop, use the same process and checks, isn't safer to extract the functionality to utils or to Manipulator.remove() instead to make inline checks?

I see what you're talking about - it looks like it's already handled correctly for the other spots:

So at least we know this PR is consistent with behavior elsewhere.

As far as extracting it to util/, I'm fine either way. Are you thinking... like a removeElementFromParent(element) function - in index.js?

Cheers!

@weaverryan weaverryan force-pushed the fix-backdrop-removed-parent branch from 18087a8 to 94d21eb Compare May 19, 2021 13:28
@GeoSot GeoSot self-assigned this May 19, 2021
@XhmikosR XhmikosR changed the title Fixing backdrop "Cannot read property 'removeChild' of null" when removed from body Fix backdrop "Cannot read property 'removeChild' of null" when removed from body May 20, 2021
@rohit2sharma95
Copy link
Collaborator

Proposal: as alert, tooltip, backdrop, use the same process and checks, isn't safer to extract the functionality to utils or to Manipulator.remove() instead to make inline checks?

Makes sense @GeoSot, but that can be done separately IMO.

PS: I am not sure why the tests are not being run here but failed when running locally on my machine.

@GeoSot
Copy link
Member

GeoSot commented May 21, 2021

@weaverryan , agreed with Rohit.

Lets fix it here, and you can open a next pr, gathering all these

@weaverryan weaverryan force-pushed the fix-backdrop-removed-parent branch 2 times, most recently from a2f321b to d3f81b6 Compare May 21, 2021 14:10
@weaverryan weaverryan force-pushed the fix-backdrop-removed-parent branch 4 times, most recently from ae07e2c to e0b81f3 Compare May 21, 2021 14:51
@weaverryan
Copy link
Contributor Author

I've just made the updates and rebased :).

Unfortunately, it looks like there are some pesky test problems. I can't repeat them locally, but each time the tests run here, the same test fails on 1 or 2 of the jobs - sometimes its Node 12, sometimes 14, etc :/.

Here's an example: https://github.com/twbs/bootstrap/pull/34014/checks?check_run_id=2640394953

I can't figure out how the new behavior would be affecting this other test :/

@alpadev
Copy link
Contributor

alpadev commented May 21, 2021

The flakyness can be explained by jasmine running the tests in random order. So if some certain test is ran before the other, things could fail that wouldn't fail in a different order.

I suspect the problem here:
https://github.com/twbs/bootstrap/blob/e0b81f331dc60ddac1e6e881b49dc3696fca16c5/js/tests/unit/util/backdrop.spec.js#L144

This will remove our fixture element and may lead to problems.

Replacing that with something like document.body.removeChild(instance._getElement()) should do it.

Edit: or you can do fixtureEl = getFixture(), after you wiped the body - I guess.

…ed from the body

Co-authored-by: Rohit Sharma <rohit2sharma95@gmail.com>
@weaverryan weaverryan force-pushed the fix-backdrop-removed-parent branch from e0b81f3 to de7b79e Compare May 21, 2021 18:20
Copy link
Contributor

@alpadev alpadev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like that did the job. 😊

LGTM 👍

@GeoSot GeoSot merged commit a2b5901 into twbs:main May 21, 2021
GeoSot pushed a commit that referenced this pull request May 21, 2021
…from the body (#34014)

Co-authored-by: Rohit Sharma <rohit2sharma95@gmail.com>
GeoSot added a commit to GeoSot/bootstrap that referenced this pull request May 21, 2021
alpadev pushed a commit that referenced this pull request May 22, 2021
Fixes regression of a2b5901 breaking the test runner because it would wipe document.body.
@weaverryan weaverryan deleted the fix-backdrop-removed-parent branch May 22, 2021 13:58
marvin-hinkley-vortx pushed a commit to Vortx-Inc/bootstrap that referenced this pull request Aug 18, 2021
…from the body (twbs#34014)

Co-authored-by: Rohit Sharma <rohit2sharma95@gmail.com>
marvin-hinkley-vortx pushed a commit to Vortx-Inc/bootstrap that referenced this pull request Aug 18, 2021
Fixes regression of twbs@a2b5901 breaking the test runner because it would wipe document.body.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Remove Modal Backdrop
4 participants