tejacques / crosstab

A utility library for cross-tab communication using localStorage.
Apache License 2.0
364 stars 58 forks source link

Prerender mode problem #52

Open turbokuzmich opened 8 years ago

turbokuzmich commented 8 years ago

Here is what i've found.

Say we have 2 pages: http://localhost:3000 and http://localhost:3000/index2.html. Each of these pages runs a script which 'unshifts' current url into array which is in localStorage. When we first open http://localhost:3000 we have [http://localhost:3000]. After navigating to http://localhost:3000/index2.html array becomes [http://localhost:3000/index2, http://localhost:3000] and so on. But some browsers (I tested in Google Chrome 47 and Safari 9) prerender pages. So when we type 'http://local' in address field, then choose http://localhost:3000/index2, change out mind, delete /index2 and go to http://localhost:3000 instead we have this: [http://localhost:3000, http://localhost:3000/index2, http://localhost:3000/index2, http://localhost:3000]. It happens because script on http://localhost:3000/index2 was executed in background mode.

I noticed that in same cases crosstab decides that my tab is not master though I only have one tab open. After studying this problem by looking at localStorage I found out that when I open new tab another nonexistent tab is already set as master. After some time (3 secs if I'm not mistaken) my tab regains master status (obviously because of keepalive loop) and everything is ok. It happens in 90% of cases. But sometimes frozen-environment problem occurs.

I think that this problem is caused by page prerender. I was able to solve it by removing frozen tab detection (here https://github.com/tejacques/crosstab/blob/master/src/crosstab.js#L753 and here https://github.com/tejacques/crosstab/blob/master/src/crosstab.js#L646-L653). Instead I forced new master tab reelection.

I suggest using page visibility API (https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API) and perform side effects only when page is not in prerender mode.

turbokuzmich commented 8 years ago

Or just use document.hidden property :)

tejacques commented 8 years ago

Thanks for reporting this. Definitely a serious bug. I have been thinking of using page visibility API for another issue so I'll see what can be done/shared.