Working with BFCache

Q: When a user clicks a link that replaces the view in the current tab with a new page, what is the fate of the nsIDOMWindow supporting the view they click on? Or: what happens when they hit the 'back' button?

A: The outer nsIDOMWindow (the |window| object in content JS, aka the <browser>'s contentWindow object in the parent document) stays right where it is. It just has its inner window and document replaced.

The inner nsIDOMWindow (the global scope object in content JS) is either thrown away when GC happens, or frozen and placed in the bfcache. When the user hits the 'back' button, either the window in bfcache is thawed or a new inner window is created, depending on whether there's a window in the bfcache.

Q: Is the page reloaded? loaded from cache? or is the DOM saved in some way as if the window was there but invisible? Are scripts recompiled? Where do they live while the page was invisible?

A: In the non-bfcache case, the page is reloaded in the sense of reparsing from the original HTML source. That might come from the HTTP cache or not, depending on whether it's been evicted; typically it does come from the HTTP cache. The DOM is recreated during the parsing process, and scripts are recompiled (and also reloaded, probably from the HTTP cache).

In the bfcache case, freezing the window just marks it as frozen; the DOM is preserved, as are compiled script objects. Thawing marks it as thawed. Freezing suspends timeouts and interval timers on the frozen window, so they won't execute. The script that's running when the window is frozen runs to completion, as it would if it were being closed, for example. After that, only scripts running on other windows can touch this window; if they modify the DOM, the cached DOM and window is thrown away.

Q: And to detect this we use pagehide/pageshow, correct?

A: That's correct. The pagehide event tells you whether the page is going into bfcache; the pageshow tells you whether it's coming from bfcache. Note that just because a page went into bfcache doesn't mean it'll ever come out again, like any other cache.

Q: Hmm, so what event tells me “you'll never get a pageshow so you can drop the megabytes of info you've saved in Firebug side table for that page?”

A: An observer notification with the topic "inner-window-destroyed" whose subject is an nsISupportsPRUint64 containing the window id of the inner window being destroyed.