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

Safari drops ticks for backgrounded tasks iOS 14 #849

Open
idoodler opened this issue Jul 10, 2020 · 13 comments
Open

Safari drops ticks for backgrounded tasks iOS 14 #849

idoodler opened this issue Jul 10, 2020 · 13 comments

Comments

@idoodler
Copy link

idoodler commented Jul 10, 2020

We are developing an Cordova based iOS App. Everything works fine on iOS 13, but we experience issues on iOS 14.

Whenever the App is sent to background and retrieved again the app is unresponsive as we use Q.js for our ViewManager.

When debugging this via the Safari Web Inspector I noticed that var def = Q.defer(); def.promise.done(function(value) { alert(value); }); def.resolve("Done") works before but not after sending the app to the background.
However native Javascript Promises work as expected new Promise(function(resolve, reject) { resolve("Done"); }).then(function(value) { alert(value) });

When inspecting the def variable using def.promise.inspect() the state is resolved and I can see the value, however none of the functions (resolve, reject, finally) are called, neither in the done, nor in the then function.

Anyone experience similar issues?

Edit:
We are using Q#1.5.1

@benjamingr
Copy link
Collaborator

Try overriding Q.nextTick (set requestTick to Promise.resolve().then(fn) and see if it helps?

@idoodler
Copy link
Author

@benjamingr No, I opened the Safari Webinspector and executed Q.nextTick = function(fn) { Promise.resolve().then(fn) } which did not change anything.

@kriskowal
Copy link
Owner

There were reports of Safari dropping timer events ages ago. I don’t know whether they went away, but your description of the problem seems to indicate a regression. Apart from looking for a more reliable primitive for timers as @benjamingr hints at, there is not a lot Q can do, and changing the underlying nextTick implementation requires very time consuming testing.

To wit, you can see some of that rigor over on https://github.com/kriskowal/asap, which I’ve not updated in ages.

It may be worthwhile to file an issue against Safari.

@kriskowal kriskowal changed the title Q.js not resolving on iOS 14 Safari drops ticks for backgrounded tasks iOS 14 Jul 10, 2020
@idoodler
Copy link
Author

I just tried to reproduce this issue with a fresh Cordova project, but I couldn't. The Promise stays alive during the application close and open. Any tips on how to debug this?

@idoodler
Copy link
Author

This issue is still present on iOS 14 Beta 3.

@idoodler
Copy link
Author

This issue is still present on iOS 14 Beta 4

@idoodler
Copy link
Author

After revisiting this issue I decided to add Q.nextTick = function(fn) { Promise.resolve().then(fn) } in our Application code (not just adding it via the Webinspector). It looks like as if this solves the issue. Does this indicate some errors in our Promise handling?

@mtamburro
Copy link

mtamburro commented Aug 25, 2020

The issue is still found on iOS 14 Beta 5 (and does not appear to affect iOS 13). Here's what I understand so far:

  1. The code path affected is the one for modern browsers where setImmediate is not defined
  2. In this path, channel.port2 posts a message, and channel.port1.onmessage responds
  3. This works, until the app goes in to the background

Here's what happens in the background:

  1. channel.port2 posts a message
  2. channel.port1 misses that message <-- I'll submit this to Apple as a difference in behavior in WKWebView on iOS 13 vs. 14
  3. this results in the flushing variable is never toggled from false to true... and no further promises are resolved

@kriskowal
Copy link
Owner

It might be helpful to reproduce and fix the problem in ASAP where we have CI that covers a broad spectrum of browsers. It would need some refreshing.

If we can address the issue in ASAP, it would give us some confidence of a solution that could be back-ported to Q. Alternately, we would need to back-port the testing setup in ASAP to give us the confidence we would need.

@msmtamburro
Copy link

FYI, I opened FB8533670 with Apple regarding a change in onmessage in WKWebView on iPadOS 14 as the App leaves the foreground. My related Apple Developer Forum post is here, for tracking.

Ended up making a temporary patch to q.js:

  • creating a backup setTimeout right before posting a message
  • clearing that timeout in flush()

When the posted message is missed, the timeout calls flush().

@msmtamburro
Copy link

FYI, I opened FB8533670 with Apple regarding a change in onmessage in WKWebView on iPadOS 14 as the App leaves the foreground. My related Apple Developer Forum post is here, for tracking.

Ended up making a temporary patch to q.js:

  • creating a backup setTimeout right before posting a message
  • clearing that timeout in flush()

When the posted message is missed, the timeout calls flush().

Apple Responded, and says this new behavior is expected: "Promptly suspending when entering the background is correct behavior according to the norm of iOS."

@kriskowal
Copy link
Owner

Maybe you can push back on Apple here. Of course it’s expected to suspend in the background. It’s also expected for the message to be delivered when returning to the foreground, unless the page is reloaded entirely. Clearly, this is a case where some timers survive stasis.

@msmtamburro
Copy link

Thanks, Kris--I actually sent this yesterday:

I do want to point out that this difference in behavior means that a message posted as the app begins to background will get “lost” rather than “handled” when the app returns to the foreground.

We'll see if we get a response.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants