[whatwg] pagehide vs pagevis

Ian Hickson ian at hixie.ch
Thu Aug 29 17:53:40 PDT 2013

On Tue, 28 May 2013, Brady Eidson wrote:
> The “unload a document” steps apparently don’t allow for the pagehide 
> event to have “persisted” set to false.

Hm, yeah, it should only be set to true if /salvageable/ is true. Fixed.

> In the original design of these events and in WebKit’s implementation, 
> pagehide with persisted “true” means the page is being suspended into 
> the page cache, and it might be restored later.  In these cases, the 
> page does not receive a traditional unload event, as it’s being 
> suspended, not unloaded.

I don't understand how you can know if you are going to fire the 'unload' 
event. I think the way the spec describes it makes more sense, which is 
that you always fire pagehide and you always fire unload, but if any 
unload handlers were triggered, then you don't suspend.

> pagehide with persisted “false” means the page is is being traditionally 
> torn down.

Right (salvageable is false).

> The spec’s description of PageTransitionEvent.persisted says "Returns 
> false if the page is newly being loaded (and the load event will fire). 
> Otherwise, returns true.”
> That text is geared towards pageshow and completely neglects pagehide.

Yeah, that description was kinda lame. Fixed.

By the way, when the spec doesn't match implementations, it's usually a 
far better bet that it's just unintentionally wrong, than that there is a 
nefarious plot to ruin everything. :-)

On Tue, 28 May 2013, Brady Eidson wrote:
> I'm sorry, who's page cache are you talking about?  Page caches are 
> (AFAIK) not really fleshed out in any spec

Actually the HTML spec defines the page cache as thoroughly (I think) as 
any spec can. (Really everything but the eviction mechanism, but that is 
intentionally a UA-specific thing.)

> and the WebKit page cache *intends* to represent a 100% inert page.  
> This includes the inability to receive events.  Any exceptions in 
> practice are a bug for us that we would strive to patch.

A DOM node can always receive an event.

The event handlers of DOM nodes in inactive documents might not be able to 
run, though. I don't think the HTML spec is very clear about this right 
now. (It blocks tasks, but I don't think it blocks event handlers.) I 
guess this would have to be in DOM, really.

I filed this so we make sure to track this:

On Wed, 29 May 2013, Brady Eidson wrote:
> Got it.  Then it sounds like Gecko’s page cache and WebKit’s page cache 
> are divergent in this regard.  Which is perfectly fine, as such a 
> browser feature isn’t spec’d anyways.

It is. :-)

> I’ve provided our rationale for changing this, and I’m formally asking 
> the WHATWG community if there’s any rationale for *not* changing this

I don't think you can formally ask anything here. You can ask, but there 
cannot be anything more or less formal about it. :-)

On Wed, 29 May 2013, Brady Eidson wrote:
> I see in the HTML spec that the step *before* firing pagehide is “set 
> the Document’s page showing flag to false,” but I can’t find language 
> that says pagehide fires *before* the page is actually hidden, and 
> unload fires *after* the page is actually hidden.

Since they fire synchronously, and rendering happens between tasks, they 
both fire when the page is in the same on-screen rendered state. I don't 
think there's a black-box way of telling whether there remains pixels of 
the page on the screen or not when either fires.

> pageshow is a history traversal event, and not a visibility event.  I 
> don’t see a guarantee in any spec that “pageshow” comes after the 
> document is actually visible.

Indeed. In fact in some UAs, e.g. those that use audio instead of video to 
display the page, the page will never be "visible".

I don't really see why it matters whether the Page Visibility spec fires 
its event before or after pagehide, though.

> First, since pagehide currently always has persisted set to true (in the 
> spec and in Gecko), it doesn’t actually describe whether or not the page 
> is going in to the page cache.

It can be false (now, in the spec) when you are definitely not going into 
the cache, but it can also be true when you're not (e.g. if WebSockets get 
killed after pagehide and unload), and it can also be true when you go 
into the cache and are immediately evicted without notice, which is much 
the same as not going into the cache.

So "true" is no guarantee of anything.

> Second, imagining a world where pagehide allows persisted to differ 
> between true or false, to know that a “hidden” corresponds with a “page 
> going in to the page cache”, you still have to listen to both events to 
> know the whole situation. Third, is the difference between 4 states and 
> 5 states really appreciable?

I don't really understand these questions.

On Thu, 30 May 2013, Brady Eidson wrote:
> Bucket 1 - “Pages not going in to the page cache”
> Let me ask you this - Are there any (reasonable) pages in the wild that 
> (reasonably) expect to do anything *after* the unload event is fired?  
> I would say no, probably not.

Sure, they expect (for instance) to have their child iframe's unload 
handlers fire and to do work there.

Assuming they don't have any child iframes, then they can't do anything 
after this point.

> If a page listens to pagehide instead of unload, then they are not 
> reasonably expecting to do anything after "pagehide with persisted set 
> to false” is fired.

Well, they're expecting to maybe see a pageshow, no?

> Would it have made sense for page-vis to put the visibilitychanged event 
> *after* unload?  I don’t think so.  No author would expect that or find 
> it very useful.

Why would they find it less useful than before pagehide?

> So I still cannot see how having it after "pagehide with persisted set 
> to false” is the right call.  Maybe authors writing to the spec might 
> expect it, but they wouldn’t find it very useful.

Well, I'm happy to change it, but I think it's probably too late now. 
You'd have to bring it up with the Page Visibility group.

> Bucket 2 - “Pages going in to the page cache”
> The long standing design goals and implementation of our page cache 
> prevents us from delivering these events to a page that was just sent 
> “pagehide with persisted set to true”.

Why not just change the implementation to have the prevention happen after 
the pagevis event?

Anyway, what if the pagehide event sets an unload handler? You'll be able 
to fire that, no?

> So it’s undesirable for two reasons:
> 1 - We can’t meet the spec.

I don't see why not.

> 2 - Authors can’t get the possible benefit that were available to them 
> if the spec was reasonable in sending visibilitychanged before pagehide 
> instead of after.

What benefit?

On Thu, 30 May 2013, Brady Eidson wrote:
> If persisted is set to true, then the page is going into the page cache.

That's not really a useful statement. It could be immediately evicted.

> If the pagehide handler does anything that prevents the page from going 
> into the page cache, then that activity would also inherently prevent 
> visibilitychanged from being observed.  (This is true in WebKit, I 
> should clarify).

I don't understand that.

> In WebKit, if you have an unload handler, you don’t go into the page 
> cache.
> Therefore if you have an unload handler, you never get "pagehide with 
> persisted set to true”

How can you know if you have an unload handler until after you've set 

On Thu, 30 May 2013, Brady Eidson wrote:
> The design of our page cache is that once “pagehide with persisted set 
> to true” returns the page is inert/suspended/paused/persisted/whatever 
> you want to call it.  It cannot receive events anymore.  It is as if it 
> had been unloaded.

Just move the code that freezes the page to after this page visibility 
event, instead of after the pagehide event.

Ian Hickson               U+1047E                )\._.,--....,'``.    fL
http://ln.hixie.ch/       U+263A                /,   _.. \   _\  ;`._ ,.
Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'

More information about the whatwg mailing list