event listeners vs window loading

NEW
Unassigned

Status

()

P5
normal
15 years ago
2 months ago

People

(Reporter: danm.moz, Unassigned)

Tracking

(Blocks: 1 bug)

Trunk
Points:
---

Firefox Tracking Flags

(Not tracked)

Details

Attachments

(1 attachment)

(Reporter)

Description

15 years ago
Bear with me for a (long) moment. This bug will display Daniel at his rambling
best. I think I have a real issue here but it'll take some explaining. At issue
is the fate of event listeners across window load boundaries. This as an adjunct
to bug 226416 and bug 197709. See those bugs for history and elucidation. In
short, I believe Mozilla's behaviour is quirky. I fear it will encourage script
authors to code workarounds specific to Mozilla and cause pointless future DOM2
cross-browser compatibility problems.

The situation is one where a script coder wants to attach listeners to a window.
(I'm considering only those situations where such a thing is considered
acceptable for privacy/security reasons. That is, on windows with content from
the same domain as the opener.) This applies to all events but I'll concentrate
on load and unload, since they serve to illustrate my point and also are very
likely the exact events a script author would be interested in using in this
situation.

The first and most obvious situation is one where the script wants to know when
a window has finished loading, or when it is no longer in service. Thus:

(1)
var newWin = window.open(<url>)
newWin.addEventListener("load", func, false)
newWin.addEventListener("unload", func, false)

There are other ways to request such notifications (e.g. attaching listeners
within the new window itself) which aren't subject to the problems I'll detail
below but this way is an important one and should work.

Thanks to bug 226416, this specific sequence does ALMOST work. Mozilla's precise
behaviour depends on the exact <url>, because of its workaround for dealing with
the initial about:blank document temporarily loaded in all new windows (bug
227028). See the chart below for details.

Now the fun begins. If the script wants to know the status of a window reload, so:

(2)
newWin.location = url

it's reasonable to expect the previously registered unload listener to fire, and
the load listener as well (as long as the new URL passes security/privacy
muster). In Mozilla, unload will fire but load will not. Event listeners can
survive only from a document whose old address was about:blank. I think that's a
problem.

So far I've established what I think is a minor bug. But it gets worse. My
biggest fear is that script authors will discover our listenercide policy and
code workarounds of a sort that will cause DOM2 cross-browser quirk problems.
Mozilla's behaviour is uniquely strange partly because of the temporary
about:blank document. So strange that I believe it's not possible to write a
script that will receive proper load and unload notifications. If you fight the
quirks you can get close but it seems to not be possible to fully succeed.

I think it's reasonable for a script author to expect this code, similar to the
standard opening sequence, to work. That is, to not hurt anything when
navigating from an URL within the script's domain to another such, and to
re-establish listeners when navigating from an URL outside to one within:

(3)
newWin.location = url
newWin.addEventListener("load", func, false)
newWin.addEventListener("unload", func, false)

I naively expected that to work. But it's not even close. The best I've been
able to manage is to try to re-establish listeners from a setTimeout(0) in the
unload handler:

(4)
var newWin = open()
newWin.addEventListener("unload",
       function() { setTimeout(reestablishListeners, 0) },
       false)
newWin.location = newUrl

This nearly works, and I believe isn't even a race condition, because of the
precise order of steps in Mozilla while reloading a window. Mozilla does nothing
until the new document begins to load. It then fires an unload event, unhooks
the old document, clears the listeners, then establishes the new document, all
in one step. The end-load and corresponding load event of course happen later.

--

So what am I saying, then? I'm saying code (1) pretty much works today, as
expected. I'm saying I rather expected code (2) to work in the absence of a
security issue. With security issues I expected code (3) to work but it doesn't.
I'm saying that without code (3) scripters will migrate to code (4), and I think
code (4) can't be guaranteed to work flawlessly with all browsers. I'm saying
"Hixie, shut my mouth."

Mostly I'm saying code (1) almost works but could stand to be better, I think
code (2) should work better, and I think code (3) should work. Code (4) can fend
for itself, if there are prettier, more direct ways to do what you want, like
code (3).

If I haven't just wasted a whole damn day crying over nothing, this is probably
a metabug.

/me does tables:

K  : event listeners were kept
R  : event listeners were removed
+U : an anomalous unload event precedes the load event (if any)
     (this is usually preceded by a focus event if the page load
     begins slowly)
-L : load event not received
~  : that's the behaviour I expected
!  : Mozilla surprises me
(n): notes

initial content:   no URL   about:blank   same origin   diff origin

listeners are:     K~-L(1)     R!+U          K~+U          R~+U

attempting to re-establish listeners (code 4):
                   K~-L(1)     K~+U-L        K~+U          R~+U

load 2nd url without attempting to re-establish listeners:
about:blank        R!                        R!
same origin        K~                        R!
diff origin        R~                        R~

load 2nd url, attempting to re-establish listeners (code 4):
about:blank        K~          K~            K~-L          R!
same origin        K~          K~            K~-L          R!
diff origin        R~          R~            R~            R~
(Reporter)

Comment 1

15 years ago
Created attachment 136903 [details]
Daniel's way the hell over the top test case
(Reporter)

Comment 2

15 years ago
Damnit. I omitted note (1) from my table:

(1) Open a new window with no URL. No events other than unload are received
until the user clicks in the new window's content area. Then everything is
hooked up. Yes, that's what I appear to be seeing. (A focus issue? I can't find
a bug for this.)
Yes.

I don't know if I expect event handlers to last across page loads, but I agree
that the current situation is suboptimal at best.

We should decide what we want and specify it formally.
Assignee: events → nobody
QA Contact: ian → events
https://bugzilla.mozilla.org/show_bug.cgi?id=1472046

Move all DOM bugs that haven’t been updated in more than 3 years and has no one currently assigned to P5.

If you have questions, please contact :mdaly.
Priority: -- → P5
You need to log in before you can comment on or make changes to this bug.