Skip to content
This repository has been archived by the owner on Jul 28, 2018. It is now read-only.

Handle errors during onload by a hard page load #669

Open
wants to merge 1 commit into
base: 2-5-stable
Choose a base branch
from

Conversation

rmosolgo
Copy link
Contributor

Recently, Safari decided that you can only pushState 100 times. After that, pushState raises "SecurityError: DOM Exception 18". Here is some more info about this change:

https://forums.developer.apple.com/thread/36650
http://codepen.io/mortenolsendk/post/when-safari-broke-webapps

This patch adds error handling to the onload hook when Turbolinks receives a new page. This way, it will catch the pushState error.

I was able to reproduce the error locally, and this patch "fixed" it for me.

(Are you still taking patches for 2-5-stable?)

@sstephenson
Copy link
Contributor

I don’t think you’re likely to encounter this in a real app. It’s a rate limit of 100 state change operations per 30 seconds, not a hard limit of 100 operations.

@rmosolgo
Copy link
Contributor Author

Thanks for those details!

Somehow, I think it is happening in our app. We've seen it on bugsnag (but I didn't look carefully, I thought it was Safari with localStorage turned off), and finally a user sent a screenshot of his JS console:

image

I'll have to read up on the 30-second limit. I found that I could replicate the issue in a timespan greater than 30 seconds:

  • Open safari

  • Open web console

  • Define turboVisit to repeatedly visit a new page with Turbolinks:

    function turboVisit(fromI, untilI, timeout) { 
      // toggle between pages in the app:
      var path = window.location.pathname == "/stations" ? "/people" : "/stations" 
      if (fromI < untilI) { 
        setTimeout(function() { turboVisit(fromI + 1, untilI, timeout) }, timeout)
      }
      console.log(fromI + ":  =>  " + window.location.pathname)
      Turbolinks.visit(path) 
    }
  • Make 120 visits, 400ms apart:

    // toggle pages 120 times, with a 400ms break in between
    turboVisit(0, 120, 400)
  • Wait:

    image

  • Interestingly, calling turboVisit(0, 120, 1000) yields a slightly different outcome (104 successful pushState calls):

    image

If I understand correctly, that's 100 * 0.400 => 40 seconds or 104 * 1 => 104 seconds, so, does that mean we're affected despite the 30s limit? Or have I overlooked something?

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

Successfully merging this pull request may close these issues.

2 participants