diff --git a/lib/browser/navigation-controller.js b/lib/browser/navigation-controller.js index c3dd89d52475..5176c8ae5410 100644 --- a/lib/browser/navigation-controller.js +++ b/lib/browser/navigation-controller.js @@ -86,10 +86,16 @@ const NavigationController = (function () { let navigationStarted = false const navigationListener = (event, url, isSameDocument, isMainFrame, frameProcessId, frameRoutingId, navigationId) => { if (isMainFrame) { - if (navigationStarted) { + if (navigationStarted && !isSameDocument) { // the webcontents has started another unrelated navigation in the // main frame (probably from the app calling `loadURL` again); reject // the promise + // We should only consider the request aborted if the "navigation" is + // actually navigating and not simply transitioning URL state in the + // current context. E.g. pushState and `location.hash` changes are + // considered navigation events but are triggered with isSameDocument. + // We can ignore these to allow virtual routing on page load as long + // as the routing does not leave the document return rejectAndCleanup(-3, 'ERR_ABORTED', url) } navigationStarted = true diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index 0c503f5b8029..b2bc71d6b4d3 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -289,6 +289,27 @@ describe('BrowserWindow module', () => { w.loadURL(`data:image/png;base64,${data}`) }) + it('should return a promise', () => { + const p = w.loadURL('about:blank') + expect(p).to.have.property('then') + }) + + it('should return a promise that resolves', async () => { + expect(w.loadURL('about:blank')).to.eventually.be.fulfilled() + }) + + it('should return a promise that rejects on a load failure', async () => { + const data = Buffer.alloc(2 * 1024 * 1024).toString('base64') + const p = w.loadURL(`data:image/png;base64,${data}`) + await expect(p).to.eventually.be.rejected() + }) + + it('should return a promise that resolves even if pushState occurs during navigation', async () => { + const data = Buffer.alloc(2 * 1024 * 1024).toString('base64') + const p = w.loadURL('data:text/html,') + await expect(p).to.eventually.be.fulfilled() + }) + describe('POST navigations', () => { afterEach(() => { w.webContents.session.webRequest.onBeforeSendHeaders(null) })