diff --git a/app/client/lib/UrlState.ts b/app/client/lib/UrlState.ts index d2487e9e..f2ad4d21 100644 --- a/app/client/lib/UrlState.ts +++ b/app/client/lib/UrlState.ts @@ -77,13 +77,23 @@ export class UrlState extends Disposable { if (samePage) { await this._stateImpl.delayPushUrl(prevState, newState); - if (options.replace) { - this._window.history.replaceState(null, '', newUrl); - } else { - this._window.history.pushState(null, '', newUrl); + try { + if (options.replace) { + this._window.history.replaceState(null, '', newUrl); + } else { + this._window.history.pushState(null, '', newUrl); + } + // pushState/replaceState above do not trigger 'popstate' event, so we call loadState() manually. + this.loadState(); + } catch (e) { + // If we fail, we may be in a context where Grist doesn't have + // control over history, e.g. an iframe with srcdoc. Go ahead + // and apply the application state change (e.g. switching to a + // different Grist page). The back button won't work, but what + // it should do in an embedded context is full of nuance anyway. + log.debug(`pushUrl failure: ${e}`); + this.state.set(this._stateImpl.decodeUrl(new URL(newUrl))); } - // pushState/replaceState above do not trigger 'popstate' event, so we call loadState() manually. - this.loadState(); } else { this._window._urlStateLoadPage!(newUrl); } diff --git a/test/fixtures/docs/SelectBySummary.grist b/test/fixtures/docs/SelectBySummary.grist index c7d67c1b..453c483f 100644 Binary files a/test/fixtures/docs/SelectBySummary.grist and b/test/fixtures/docs/SelectBySummary.grist differ diff --git a/test/nbrowser/SelectByRefList.ts b/test/nbrowser/SelectByRefList.ts index 7982817c..34bbb860 100644 --- a/test/nbrowser/SelectByRefList.ts +++ b/test/nbrowser/SelectByRefList.ts @@ -4,7 +4,7 @@ import * as gu from 'test/nbrowser/gristUtils'; import {server, setupTestSuite} from 'test/nbrowser/testUtils'; describe('SelectByRefList', function() { - this.timeout(60000); + this.timeout(80000); setupTestSuite(); addToRepl('gu2', gu); gu.bigScreen();