After very specific browser navigation, a Greasemonkey script will be
applied to a page twice. There are a number of easy workarounds, but
I doubt that this is intended behavior. To reproduce the bug, I've
created a simple document:
http://vestitools.pbworks.com/f/gmbugtest.html
If you go there, you'll see a textarea, a link, a button to clear the
textarea, and a button that does nothing. I created a script to go
along with this page:
http://vestitools.pbworks.com/f/gmbugtest.user.js
What the script does is set a variable to true, set a variable in
unsafeWindow to true, append an element to the body of the page, and
add an event listener to the button that does nothing so that it posts
a message to the textarea when clicked.
To reproduce the bug, follow these steps:
1. Install the test script
2. Go to the test site
3. Click the "Link to another site" (last.fm)
4. AFTER you see the content of the window change, but BEFORE the
page fully loads, hit Backspace or click the back button. Generally,
I hit backspace immediately when I see the title of the page change.
You may need to try this a few times until you encounter the bug,
especially if the site loads quickly.
At this point, if you did step 4 correctly, the script will have been
applied to the page twice. You'll notice that there are two appended
elements instead of one. The script will have detected that the
unsafeWindow variable was already set, but the "local" variable does
not seem to be set, indicating that the two script instances are in
different sandboxes. If you click the do nothing button, two messages
will be posted to the textarea instead of one, indicating that there
are two event listeners.
If you uncomment the line at the top of the script, it will detect
when this problem occurs, let you know, and stop execution. If you
refresh the page when you have extra scripts running, the page will
refresh properly and you'll only get one script running.
I'm guessing that Firefox/Greasemonkey doesn't fully destroy the old
page environment until the next page is drawn, so when you go back to
the old page, it loads it from memory/cache, another load event is
fired, and Greasemonkey applies the script again. Perhaps this is a
bug in Firefox itself, and the extra load event should not be fired.
I originally encountered this with a larger script of my own. Users
were complaining about some actions handled by event listeners
occurring twice. I had no idea what the problem was, I just assumed
they had two copies of the script installed or something. I then
encountered the problem myself and discovered how to reproduce it.
Let me know if you can successfully reproduce this. I can do it on
another profile that has very few extensions installed.
This is called "fastback".
> another load event is
> fired, and Greasemonkey applies the script again. Perhaps this is a
> bug in Firefox itself, and the extra load event should not be fired.
Yes, it shouldn't fire DOMContentLoaded if it didn't load the DOM (but
rather restore the fastback cached version).
I've filed a bug at bugzilla.mozilla.org about this issue.
https://bugzilla.mozilla.org/show_bug.cgi?id=548145
The jury is still out on if the event should fire or not.
"During a page transition, there are two documents that are "live" (in
the sense of script
possibly running on them) at the same time; they will generally have
different
URIs, and will have different inner windows (script global objects)
but share a
single outer window (navigation context). The defaultView property
returns the
_outer_ window.
So a situation in which doc.documentURI !=
doc.defaultView.location.href is
normal during a page transition. If Greasemonkey is really trying to
tell the
"document location" for the document which fired DOMContentLoaded, it
needs to
be looking at the document, not the window."