Skip to content
This repository was archived by the owner on Mar 13, 2018. It is now read-only.

Commit 55aada6

Browse files
author
John Messerly
committed
Re-land fix for unload/beforeunload events, fixes https://github.com/Polymer/platform/issues/83
1 parent 5230708 commit 55aada6

File tree

3 files changed

+65
-5
lines changed

3 files changed

+65
-5
lines changed

src/wrappers/events.js

+21-5
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,19 @@
237237
}
238238
}
239239

240+
241+
function isLoadLikeEvent(event) {
242+
switch (event.type) {
243+
// http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#events-and-the-window-object
244+
case 'load':
245+
// http://www.whatwg.org/specs/web-apps/current-work/multipage/browsers.html#unloading-documents
246+
case 'beforeunload':
247+
case 'unload':
248+
return true;
249+
}
250+
return false;
251+
}
252+
240253
function dispatchEvent(event, originalWrapperTarget) {
241254
if (currentlyDispatchingEvents.get(event))
242255
throw new Error('InvalidStateError');
@@ -254,12 +267,11 @@
254267
// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#the-end
255268
var overrideTarget;
256269
var win;
257-
var type = event.type;
258270

259271
// Should really be not cancelable too but since Firefox has a bug there
260272
// we skip that check.
261273
// https://bugzilla.mozilla.org/show_bug.cgi?id=999456
262-
if (type === 'load' && !event.bubbles) {
274+
if (isLoadLikeEvent(event) && !event.bubbles) {
263275
var doc = originalWrapperTarget;
264276
if (doc instanceof wrappers.Document && (win = doc.defaultView)) {
265277
overrideTarget = doc;
@@ -274,7 +286,7 @@
274286
} else {
275287
eventPath = getEventPath(originalWrapperTarget, event);
276288

277-
if (event.type !== 'load') {
289+
if (!isLoadLikeEvent(event)) {
278290
var doc = eventPath[eventPath.length - 1];
279291
if (doc instanceof wrappers.Document)
280292
win = doc.defaultView;
@@ -380,7 +392,6 @@
380392
var type = event.type;
381393

382394
var anyRemoved = false;
383-
// targetTable.set(event, target);
384395
targetTable.set(event, target);
385396
currentTargetTable.set(event, currentTarget);
386397

@@ -465,7 +476,12 @@
465476
function Event(type, options) {
466477
if (type instanceof OriginalEvent) {
467478
var impl = type;
468-
if (!OriginalBeforeUnloadEvent && impl.type === 'beforeunload') {
479+
// In browsers that do not correctly support BeforeUnloadEvent we get to
480+
// the generic Event wrapper but we still want to ensure we create a
481+
// BeforeUnloadEvent. Since BeforeUnloadEvent calls super, we need to
482+
// prevent reentrancty.
483+
if (!OriginalBeforeUnloadEvent && impl.type === 'beforeunload' &&
484+
!(this instanceof BeforeUnloadEvent)) {
469485
return new BeforeUnloadEvent(impl);
470486
}
471487
setWrapper(impl, this);

test/html/on-unload-test.html

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<!DOCTYPE html>
2+
<script src="../../../tools/test/chai/chai.js"></script>
3+
<script src="../../../tools/test/htmltest.js"></script>
4+
<script src="../../shadowdom.js"></script>
5+
<script>
6+
// Note: this test will navigate away from the page. It is designed to be run
7+
// in an iframe. Use ShadowDOM/test/runner.html?grep=unload for running it by
8+
// itself.
9+
10+
function runTest() {
11+
var assert = chai.assert;
12+
var doc = ShadowDOMPolyfill.wrap(document);
13+
var win = ShadowDOMPolyfill.wrap(window);
14+
15+
// Note: IE gives `window` as the target for beforeunload/unload. Others give
16+
// document. It's not clear than anyone gets it right, my reading of the
17+
// current spec is target should be window for beforeunload, but is overridden
18+
// to be document for unload. Both events are dispatched on window:
19+
// http://www.whatwg.org/specs/web-apps/current-work/multipage/browsers.html#unloading-documents
20+
var expectedTarget = /Trident/.test(navigator.userAgent) ? win : doc;
21+
22+
var beforeunloadCalled = 0;
23+
window.addEventListener('beforeunload', function(e) {
24+
beforeunloadCalled++;
25+
assert.equal(e.target, expectedTarget);
26+
});
27+
28+
window.addEventListener('unload', function(e) {
29+
assert.equal(beforeunloadCalled, 1);
30+
assert.equal(e.target, expectedTarget);
31+
done();
32+
});
33+
34+
location.href = 'about:blank';
35+
}
36+
37+
document.addEventListener('DOMContentLoaded', function(e) {
38+
// Note: setTimeout makes IE happy. If document.readyState == 'interactive'
39+
// at the time we run the tests, IE won't fire an unload in the iframe.
40+
setTimeout(runTest, 0);
41+
});
42+
43+
</script>

test/js/events.js

+1
Original file line numberDiff line numberDiff line change
@@ -928,6 +928,7 @@ test('retarget order (multiple shadow roots)', function() {
928928
});
929929

930930
htmlTest('html/on-load-test.html');
931+
htmlTest('html/on-unload-test.html');
931932

932933
test('event wrap round trip', function() {
933934
var e = new Event('x');

0 commit comments

Comments
 (0)