From e9ee46b39828d50756ffef0465a0e900ff63fafb Mon Sep 17 00:00:00 2001 From: Paul Sherman Date: Mon, 27 Aug 2018 23:43:02 -0500 Subject: [PATCH] Add fallbacks for push/replace state calls --- BROWSER_COMPATIBILITY.md | 8 +++----- packages/browser/src/index.ts | 12 ++++++++++-- packages/hash/src/index.ts | 12 ++++++++++-- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/BROWSER_COMPATIBILITY.md b/BROWSER_COMPATIBILITY.md index 0d3f74c..6d94e60 100644 --- a/BROWSER_COMPATIBILITY.md +++ b/BROWSER_COMPATIBILITY.md @@ -2,10 +2,8 @@ These are mostly gleaned from bug fixes in the `history` package. -1. Internet Explorer 10/11 do not emit `popstate` events when only the `hash` segment of the URI changes. In order to deal with that, we need to detect those browsers and also add `hashchange` listeners. +1. Internet Explorer 10/11 do not emit `popstate` events when only the `hash` segment of the URI changes. In order to deal with that, we need to detect those browsers and also add `hashchange` listeners. -2. Internet Explorer 11 will sometimes throw errors when attempting to access `window.history.state`. In order to deal with that, we need to wrap access to that in a `try...catch` and just return an empty object when that happens. +2. Internet Explorer 11 will sometimes throw errors when attempting to access `window.history.state`. In order to deal with that, we need to wrap access to that in a `try...catch` and just return an empty object when that happens. -3. In Webkit browsers, there can be extra `popstate` events that we want to ignore. To deal with this, we can ignore these events when `event.state` is `undefined` (unless we are in Chrome on iOS). - -4. iOS Safari will through an exception if there are 100 `pushState`/`replaceState` calls in a 30 second window. This could be avoided by catching the exception and calling `window.location.(assign|replace)`, but a fix is not currently implemented because this is an exception that will (almost?) always be caused by an abusive website. +3. In Webkit browsers, there can be extra `popstate` events that we want to ignore. To deal with this, we can ignore these events when `event.state` is `undefined` (unless we are in Chrome on iOS). diff --git a/packages/browser/src/index.ts b/packages/browser/src/index.ts index 4fc24fa..8271ed7 100644 --- a/packages/browser/src/index.ts +++ b/packages/browser/src/index.ts @@ -104,7 +104,11 @@ export default function Browser(options: Options = {}): History { return () => { const path = toHref(location); const { key, state } = location; - window.history.pushState({ key, state }, "", path); + try { + window.history.pushState({ key, state }, "", path); + } catch (e) { + window.location.assign(path); + } browserHistory.location = location; browserHistory.action = "PUSH"; }; @@ -114,7 +118,11 @@ export default function Browser(options: Options = {}): History { return () => { const path = toHref(location); const { key, state } = location; - window.history.replaceState({ key, state }, "", path); + try { + window.history.replaceState({ key, state }, "", path); + } catch (e) { + window.location.replace(path); + } browserHistory.location = location; browserHistory.action = "REPLACE"; }; diff --git a/packages/hash/src/index.ts b/packages/hash/src/index.ts index 30e0bcb..c967775 100644 --- a/packages/hash/src/index.ts +++ b/packages/hash/src/index.ts @@ -116,7 +116,11 @@ export default function HashHistory(options: Options = {}): History { return () => { const path = toHref(location); const { key, state } = location; - window.history.pushState({ key, state }, "", path); + try { + window.history.pushState({ key, state }, "", path); + } catch (e) { + window.location.assign(path); + } hashHistory.location = location; hashHistory.action = "PUSH"; }; @@ -126,7 +130,11 @@ export default function HashHistory(options: Options = {}): History { return () => { const path = toHref(location); const { key, state } = location; - window.history.replaceState({ key, state }, "", path); + try { + window.history.replaceState({ key, state }, "", path); + } catch (e) { + window.location.replace(path); + } hashHistory.location = location; hashHistory.action = "REPLACE"; };