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(client): fix a false positive page reload error in Safari #3643

Merged
merged 1 commit into from
Feb 1, 2021

Conversation

devoto13
Copy link
Collaborator

Previous code was susceptible to the race condition in Safari browser. Specifically below piece:

iframe.src = policy.createURL(url)
karmaNavigating = false

There is no guarantee that onbeforeunload event will be triggered synchronously after setting iframe.src. It was the case in Chrome and Firefox, but not in Safari, where this caused an error every test run. New approach resets the onbeforeunload handler before navigation is triggered by Karma itself to avoid the need for synchronization and this race condition altogether. The handler will be restored by the new context once it is loaded.

PS Code is a bit fragile as there is an implicit dependency on onbeforeunload from the context, but I can't think of a cleaner approach.

@karmarunnerbot
Copy link
Member

Build karma 511 completed (commit 57e96aab43 by @devoto13)

@karmarunnerbot
Copy link
Member

Build karma 510 completed (commit 57e96aab43 by @devoto13)

Previous code was susceptible to the race condition in Safari browser. Specifically below piece:

```
iframe.src = policy.createURL(url)
karmaNavigating = false
```

There is no guarantee that onbeforeunload event will be triggered synchronously after setting `iframe.src`. It was the case in Chrome and Firefox, but not in Safari, where this caused an error every test run. New approach resets the onbeforeunload handler before navigation is triggered by Karma itself to avoid the need for synchronization and this race condition altogether. The handler will be restored by the new context once it is loaded.

PS Code is a bit fragile as there is an implicit dependency on `onbeforeunload` from the context, but I can't think of a cleaner approach.
@karmarunnerbot
Copy link
Member

Build karma 513 completed (commit 456e5e1f0d by @devoto13)

@karmarunnerbot
Copy link
Member

Build karma 512 completed (commit 456e5e1f0d by @devoto13)

Copy link
Contributor

@johnjbarton johnjbarton left a comment

Choose a reason for hiding this comment

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

This solution seems much cleaner but I don't follow the explanation.

The old code was like

karmaNavigating = true
iframe.src = policy.createURL(url)
karmaNavigating = false

So I guess you are saying that iframe.src = was triggering onbeforeunload but not synchronously on safari. Thus the trailing karmaNavigating = false ran before the handler could check it.

The new solution removes the onbeforeunload handler before iframe.src = then the iframe content (context) adds it back.

Ok I see. The new solution adds the onbeforeunload handler at the start of the context execution, then the client removes the handler whenever it is going to navigate an existing context window, thus avoiding the error on navigation without needing a flag.

if (self.config.useIframe === false) {
// run in new window
if (self.config.runInParent === false) {
// If there is a window already open, then close it
// DEV: In some environments (e.g. Electron), we don't have setter access for location
if (childWindow !== null && childWindow.closed !== true) {
// The onbeforeunload listener was added by context to catch
// unexpected navigations while running tests.
childWindow.onbeforeunload = undefined
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not delete childWindow.onbeforeunload?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

onbeforeunload is a property of the window object, i.e. it has getter and setter. window.onbeforeunload = undefined will change the underlying value, while delete window.onbeforeunload will remove the property descriptor. Consider the below screenshot:

image

It does not really matter in this case, but I think the current code is more correct.

@@ -128,15 +127,10 @@ function Karma (updater, socket, iframe, opener, navigator, location, document)
}
// run in iframe
} else {
// The onbeforeunload listener was added by the context to catch
// unexpected navigations while running tests.
iframe.contentWindow.onbeforeunload = undefined
Copy link
Contributor

Choose a reason for hiding this comment

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

same q

@johnjbarton
Copy link
Contributor

Merge once you consider my comments

@johnjbarton johnjbarton merged commit 2a57b23 into karma-runner:master Feb 1, 2021
@devoto13 devoto13 deleted the fix-page-reload branch February 1, 2021 19:58
karmarunnerbot pushed a commit that referenced this pull request Feb 1, 2021
## [6.0.4](v6.0.3...v6.0.4) (2021-02-01)

### Bug Fixes

* **cli:** temporarily disable strict parameters validation ([#3641](#3641)) ([9c755e0](9c755e0)), closes [#3625](#3625)
* **client:** fix a false positive page reload error in Safari ([#3643](#3643)) ([2a57b23](2a57b23))
* ensure that Karma supports running tests on IE 11 ([#3642](#3642)) ([dbd1943](dbd1943))
@karmarunnerbot
Copy link
Member

🎉 This PR is included in version 6.0.4 🎉

The release is available on:

Your semantic-release bot 📦🚀

@XhmikosR
Copy link
Contributor

XhmikosR commented Feb 2, 2021

Thank you for this fix! We were hitting this on our v4-dev branch consistently, but on main it didn't happen even though we do test Safari there too, but a newer version.

This was referenced Mar 14, 2021
anthony-redFox pushed a commit to anthony-redFox/karma that referenced this pull request May 16, 2023
…runner#3643)

Previous code was susceptible to the race condition in Safari browser. Specifically below piece:

```
iframe.src = policy.createURL(url)
karmaNavigating = false
```

There is no guarantee that onbeforeunload event will be triggered synchronously after setting `iframe.src`. It was the case in Chrome and Firefox, but not in Safari, where this caused an error every test run. New approach resets the onbeforeunload handler before navigation is triggered by Karma itself to avoid the need for synchronization and this race condition altogether. The handler will be restored by the new context once it is loaded.

PS Code is a bit fragile as there is an implicit dependency on `onbeforeunload` from the context, but I can't think of a cleaner approach.
anthony-redFox pushed a commit to anthony-redFox/karma that referenced this pull request May 16, 2023
## [6.0.4](karma-runner/karma@v6.0.3...v6.0.4) (2021-02-01)

### Bug Fixes

* **cli:** temporarily disable strict parameters validation ([karma-runner#3641](karma-runner#3641)) ([9c755e0](karma-runner@9c755e0)), closes [karma-runner#3625](karma-runner#3625)
* **client:** fix a false positive page reload error in Safari ([karma-runner#3643](karma-runner#3643)) ([2a57b23](karma-runner@2a57b23))
* ensure that Karma supports running tests on IE 11 ([karma-runner#3642](karma-runner#3642)) ([dbd1943](karma-runner@dbd1943))
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.

4 participants