| Index: safari/ext/background.js | 
| =================================================================== | 
| --- a/safari/ext/background.js | 
| +++ b/safari/ext/background.js | 
| @@ -22,12 +22,11 @@ | 
| var pages = {__proto__: null}; | 
| var pageCounter = 0; | 
| - var Page = function(id, tab, url, prerendered) | 
| + var Page = function(id, tab, url) | 
| { | 
| this._id = id; | 
| this._tab = tab; | 
| this._frames = [{url: url, parent: null}]; | 
| - this._prerendered = prerendered; | 
| if (tab.page) | 
| this._messageProxy = new ext._MessageProxy(tab.page); | 
| @@ -64,20 +63,25 @@ | 
| var isPageActive = function(page) | 
| { | 
| - return page._tab == page._tab.browserWindow.activeTab && !page._prerendered; | 
| + var tab = page._tab; | 
| + return tab == tab.browserWindow.activeTab && page == tab._visiblePage; | 
| }; | 
| var forgetPage = function(id) | 
| { | 
| ext._removeFromAllPageMaps(id); | 
| + | 
| + delete pages[id]._tab._pages[id]; | 
| delete pages[id]; | 
| }; | 
| var replacePage = function(page) | 
| { | 
| - for (var id in pages) | 
| + page._tab._visiblePage = page; | 
| + | 
| + for (var id in page._tab._pages) | 
| { | 
| - if (id != page._id && pages[id]._tab == page._tab) | 
| + if (id != page._id) | 
| forgetPage(id); | 
| } | 
| @@ -139,11 +143,8 @@ | 
| // tab. Note that it wouldn't be sufficient do that when the old page | 
| // is unloading, because Safari dispatches window.onunload only when | 
| // reloading the page or following links, but not when closing the tab. | 
| - for (var id in pages) | 
| - { | 
| - if (pages[id]._tab == event.target) | 
| - forgetPage(id); | 
| - } | 
| + for (var id in event.target._pages) | 
| + forgetPage(id); | 
| }, true); | 
| @@ -227,18 +228,7 @@ | 
| // became active. If we can't find that page (e.g. when a page was | 
| // opened in a new tab, and our content script didn't run yet), the | 
| // toolbar item of the window, is reset to its intial configuration. | 
| - var activePage = null; | 
| - for (var id in pages) | 
| - { | 
| - var page = pages[id]; | 
| - if (page._tab == event.target && !page._prerendered) | 
| - { | 
| - activePage = page; | 
| - break; | 
| - } | 
| - } | 
| - | 
| - updateToolbarItemForPage(activePage, event.target.browserWindow); | 
| + updateToolbarItemForPage(event.target._visiblePage, event.target.browserWindow); | 
| }, true); | 
| @@ -540,11 +530,9 @@ | 
| // by matching its referrer with the URL of frames previously | 
| // loaded in the same tab. If there is more than one match, | 
| // the most recent loaded page and frame is preferred. | 
| - for (var curPageId in pages) | 
| + for (var curPageId in (tab ? tab._pages : pages)) | 
| { | 
| var curPage = pages[curPageId]; | 
| - if (tab && curPage._tab != tab) | 
| - continue; | 
| for (var i = 0; i < curPage._frames.length; i++) | 
| { | 
| @@ -580,36 +568,33 @@ | 
| switch (event.message.category) | 
| { | 
| case "loading": | 
| + var tab = event.target; | 
| + var message = event.message; | 
| + | 
| var pageId; | 
| var frameId; | 
| - if (event.message.isTopLevel) | 
| + if (message.isTopLevel) | 
| { | 
| pageId = ++pageCounter; | 
| frameId = 0; | 
| - var isPrerendered = event.message.isPrerendered; | 
| - var page = new Page( | 
| - pageId, | 
| - event.target, | 
| - event.message.url, | 
| - isPrerendered | 
| - ); | 
| + var page = new Page(pageId, tab, message.url); | 
| - if (event.message.isPopup && !event.target._popupLoaded) | 
| + if (message.isPopup && !tab._popupLoaded) | 
| { | 
| - if (!("_opener" in event.target)) | 
| - event.target._opener = findPageAndFrame(null, event.message.referrer); | 
| + if (!("_opener" in tab)) | 
| + tab._opener = findPageAndFrame(null, message.referrer); | 
| if (page.url != "about:blank") | 
| - event.target._popupLoaded = true; | 
| + tab._popupLoaded = true; | 
| - ext.pages.onPopup._dispatch(page, event.target._opener); | 
| + ext.pages.onPopup._dispatch(page, tab._opener); | 
| } | 
| - if (event.target.browserWindow) | 
| + if (tab.browserWindow) | 
| { | 
| - pages[pageId] = page; | 
| + pages[pageId] = (tab._pages || (tab._pages = {__proto__: null}))[pageId] = page; | 
| 
 
Wladimir Palant
2014/06/11 08:17:10
Seriously, don't be too clever - go for readable c
 
 | 
| // when a new page is shown, forget the previous page associated | 
| // with its tab, and reset the toolbar item if necessary. | 
| @@ -617,7 +602,7 @@ | 
| // page is unloading, because Safari dispatches window.onunload | 
| // only when reloading the page or following links, but not when | 
| // you enter a new URL in the address bar. | 
| - if (!isPrerendered) | 
| + if (!message.isPrerendered) | 
| replacePage(page); | 
| ext.pages.onLoading._dispatch(page); | 
| @@ -625,15 +610,12 @@ | 
| } | 
| else | 
| { | 
| - var parent = findPageAndFrame(event.target, event.message.referrer); | 
| + var parent = findPageAndFrame(tab, message.referrer); | 
| pageId = parent.page._id; | 
| frameId = parent.page._frames.length; | 
| - parent.page._frames.push({ | 
| - url: event.message.url, | 
| - parent: parent.frame | 
| - }); | 
| + parent.page._frames.push({url: message.url, parent: parent.frame}); | 
| } | 
| event.message = {pageId: pageId, frameId: frameId}; | 
| @@ -662,16 +644,13 @@ | 
| pages[event.message.pageId]._messageProxy.handleResponse(event.message); | 
| break; | 
| case "replaced": | 
| - var page = pages[event.message.pageId]; | 
| - page._prerendered = false; | 
| - | 
| // when a prerendered page is shown, forget the previous page | 
| // associated with its tab, and reset the toolbar item if necessary. | 
| // Note that it wouldn't be sufficient to do that when the old | 
| // page is unloading, because Safari dispatches window.onunload | 
| // only when reloading the page or following links, but not when | 
| // the current page is replaced with a prerendered page. | 
| - replacePage(page); | 
| + replacePage(pages[event.message.pageId]); | 
| break; | 
| } | 
| }); |