2011-04-21 20:17:31 -07:00
|
|
|
<!DOCTYPE HTML>
|
|
|
|
<html>
|
|
|
|
<!--
|
|
|
|
https://bugzilla.mozilla.org/show_bug.cgi?id=542058
|
|
|
|
-->
|
|
|
|
<head>
|
|
|
|
<title>Test for MediaQueryList (Bug 542058)</title>
|
|
|
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
|
|
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
|
|
|
</head>
|
|
|
|
<body onload="run()">
|
|
|
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=542058">Mozilla Bug 542058</a>
|
|
|
|
<iframe id="subdoc" src="about:blank"></iframe>
|
|
|
|
<div id="content" style="display:none"></div>
|
|
|
|
<pre id="test">
|
|
|
|
<script type="application/javascript">
|
|
|
|
|
|
|
|
/** Test for MediaQueryList (Bug 542058) **/
|
|
|
|
|
|
|
|
SimpleTest.waitForExplicitFinish();
|
|
|
|
|
|
|
|
function run() {
|
|
|
|
var iframe = document.getElementById("subdoc");
|
|
|
|
var subdoc = iframe.contentDocument;
|
|
|
|
var subwin = iframe.contentWindow;
|
|
|
|
var subroot = subdoc.documentElement;
|
|
|
|
|
|
|
|
var content_div = document.getElementById("content");
|
2012-10-30 08:57:36 -07:00
|
|
|
content_div.style.font = "initial";
|
2011-04-21 20:17:31 -07:00
|
|
|
var em_size =
|
|
|
|
getComputedStyle(content_div, "").fontSize.match(/^(\d+)px$/)[1];
|
|
|
|
|
|
|
|
var w = Math.floor(em_size * 9.3);
|
|
|
|
var h = Math.floor(em_size * 4.2);
|
|
|
|
iframe.style.width = w + "px";
|
|
|
|
iframe.style.height = h + "px";
|
|
|
|
subroot.offsetWidth; // flush layout
|
|
|
|
|
|
|
|
function setup_mql(str) {
|
2012-02-29 20:47:55 -08:00
|
|
|
var obj = {
|
|
|
|
str: str,
|
|
|
|
mql: subwin.matchMedia(str),
|
|
|
|
notifyCount: 0,
|
|
|
|
listener: function(mql) {
|
|
|
|
is(mql, obj.mql,
|
|
|
|
"correct argument to listener: " + obj.str);
|
|
|
|
++obj.notifyCount;
|
|
|
|
// Test the last match result only on odd
|
|
|
|
// notifications.
|
|
|
|
if (obj.notifyCount & 1) {
|
|
|
|
obj.lastOddMatchResult = mql.matches;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
obj.mql.addListener(obj.listener);
|
2011-04-21 20:17:31 -07:00
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
2012-02-29 20:47:55 -08:00
|
|
|
function finish_mql(obj) {
|
|
|
|
obj.mql.removeListener(obj.listener);
|
|
|
|
}
|
|
|
|
|
2011-04-21 20:17:31 -07:00
|
|
|
var w_exact_w = setup_mql("(width: " + w + "px)");
|
|
|
|
var w_min_9em = setup_mql("(min-width : 9em)");
|
|
|
|
var w_min_10em = setup_mql("( min-width: 10em ) ");
|
|
|
|
var w_max_9em = setup_mql("(max-width: 9em)");
|
|
|
|
var w_max_10em = setup_mql("(max-width: 10em)");
|
|
|
|
|
|
|
|
is(w_exact_w.mql.media, "(width: " + w + "px)", "serialization");
|
|
|
|
is(w_min_9em.mql.media, "(min-width: 9em)", "serialization");
|
|
|
|
is(w_min_10em.mql.media, "(min-width: 10em)", "serialization");
|
|
|
|
is(w_max_9em.mql.media, "(max-width: 9em)", "serialization");
|
|
|
|
is(w_max_10em.mql.media, "(max-width: 10em)", "serialization");
|
|
|
|
|
|
|
|
function check_match(obj, expected, desc) {
|
|
|
|
is(obj.mql.matches, expected,
|
|
|
|
obj.str + " media query list .matches " + desc);
|
|
|
|
if (obj.notifyCount & 1) { // odd notifications only
|
|
|
|
is(obj.lastOddMatchResult, expected,
|
|
|
|
obj.str + " media query list last notify result " + desc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function check_notify(obj, expected, desc) {
|
|
|
|
is(obj.notifyCount, expected,
|
|
|
|
obj.str + " media query list .notify count " + desc);
|
|
|
|
}
|
|
|
|
check_match(w_exact_w, true, "initially");
|
|
|
|
check_notify(w_exact_w, 0, "initially");
|
|
|
|
check_match(w_min_9em, true, "initially");
|
|
|
|
check_notify(w_min_9em, 0, "initially");
|
|
|
|
check_match(w_min_10em, false, "initially");
|
|
|
|
check_notify(w_min_10em, 0, "initially");
|
|
|
|
check_match(w_max_9em, false, "initially");
|
|
|
|
check_notify(w_max_9em, 0, "initially");
|
|
|
|
check_match(w_max_10em, true, "initially");
|
|
|
|
check_notify(w_max_10em, 0, "initially");
|
|
|
|
|
|
|
|
var w2 = Math.floor(em_size * 10.3);
|
|
|
|
iframe.style.width = w2 + "px";
|
|
|
|
subroot.offsetWidth; // flush layout
|
|
|
|
|
|
|
|
check_match(w_exact_w, false, "after width increase to around 10.3em");
|
|
|
|
check_notify(w_exact_w, 1, "after width increase to around 10.3em");
|
|
|
|
check_match(w_min_9em, true, "after width increase to around 10.3em");
|
|
|
|
check_notify(w_min_9em, 0, "after width increase to around 10.3em");
|
|
|
|
check_match(w_min_10em, true, "after width increase to around 10.3em");
|
|
|
|
check_notify(w_min_10em, 1, "after width increase to around 10.3em");
|
|
|
|
check_match(w_max_9em, false, "after width increase to around 10.3em");
|
|
|
|
check_notify(w_max_9em, 0, "after width increase to around 10.3em");
|
|
|
|
check_match(w_max_10em, false, "after width increase to around 10.3em");
|
|
|
|
check_notify(w_max_10em, 1, "after width increase to around 10.3em");
|
|
|
|
|
|
|
|
var w3 = w * 2;
|
|
|
|
iframe.style.width = w3 + "px";
|
|
|
|
subroot.offsetWidth; // flush layout
|
|
|
|
|
|
|
|
check_match(w_exact_w, false, "after width double from original");
|
|
|
|
check_notify(w_exact_w, 1, "after width double from original");
|
|
|
|
check_match(w_min_9em, true, "after width double from original");
|
|
|
|
check_notify(w_min_9em, 0, "after width double from original");
|
|
|
|
check_match(w_min_10em, true, "after width double from original");
|
|
|
|
check_notify(w_min_10em, 1, "after width double from original");
|
|
|
|
check_match(w_max_9em, false, "after width double from original");
|
|
|
|
check_notify(w_max_9em, 0, "after width double from original");
|
|
|
|
check_match(w_max_10em, false, "after width double from original");
|
|
|
|
check_notify(w_max_10em, 1, "after width double from original");
|
|
|
|
|
|
|
|
SpecialPowers.setFullZoom(subwin, 2.0);
|
|
|
|
subroot.offsetWidth; // flush layout
|
|
|
|
|
|
|
|
check_match(w_exact_w, true, "after zoom");
|
|
|
|
check_notify(w_exact_w, 2, "after zoom");
|
|
|
|
check_match(w_min_9em, true, "after zoom");
|
|
|
|
check_notify(w_min_9em, 0, "after zoom");
|
|
|
|
check_match(w_min_10em, false, "after zoom");
|
|
|
|
check_notify(w_min_10em, 2, "after zoom");
|
|
|
|
check_match(w_max_9em, false, "after zoom");
|
|
|
|
check_notify(w_max_9em, 0, "after zoom");
|
|
|
|
check_match(w_max_10em, true, "after zoom");
|
|
|
|
check_notify(w_max_10em, 2, "after zoom");
|
|
|
|
|
|
|
|
SpecialPowers.setFullZoom(subwin, 1.0);
|
|
|
|
|
2012-02-29 20:47:55 -08:00
|
|
|
finish_mql(w_exact_w);
|
|
|
|
finish_mql(w_min_9em);
|
|
|
|
finish_mql(w_min_10em);
|
|
|
|
finish_mql(w_max_9em);
|
|
|
|
finish_mql(w_max_10em);
|
|
|
|
|
2011-04-21 20:17:31 -07:00
|
|
|
// Additional tests of listener mutation.
|
|
|
|
(function() {
|
|
|
|
var received = [];
|
|
|
|
var received_mql = [];
|
|
|
|
function listener1(mql) {
|
|
|
|
received.push(1);
|
|
|
|
received_mql.push(mql);
|
|
|
|
}
|
|
|
|
function listener2(mql) {
|
|
|
|
received.push(2);
|
|
|
|
received_mql.push(mql);
|
|
|
|
}
|
|
|
|
|
|
|
|
iframe.style.width = "200px";
|
|
|
|
subroot.offsetWidth; // flush layout
|
|
|
|
|
|
|
|
var mql = subwin.matchMedia("(min-width: 150px)");
|
|
|
|
mql.addListener(listener1);
|
|
|
|
mql.addListener(listener1);
|
|
|
|
mql.addListener(listener2);
|
|
|
|
is(JSON.stringify(received), "[]", "listeners before notification");
|
|
|
|
|
|
|
|
iframe.style.width = "100px";
|
|
|
|
subroot.offsetWidth; // flush layout
|
|
|
|
|
|
|
|
is(JSON.stringify(received), "[1,2]", "duplicate listeners removed");
|
|
|
|
received = [];
|
|
|
|
mql.removeListener(listener1);
|
|
|
|
|
|
|
|
iframe.style.width = "200px";
|
|
|
|
subroot.offsetWidth; // flush layout
|
|
|
|
|
|
|
|
is(JSON.stringify(received), "[2]", "listener removal");
|
|
|
|
received = [];
|
|
|
|
mql.addListener(listener1);
|
|
|
|
|
|
|
|
iframe.style.width = "100px";
|
|
|
|
subroot.offsetWidth; // flush layout
|
|
|
|
|
|
|
|
is(JSON.stringify(received), "[2,1]", "listeners notified in order");
|
|
|
|
received = [];
|
|
|
|
mql.addListener(listener2);
|
|
|
|
|
|
|
|
iframe.style.width = "200px";
|
|
|
|
subroot.offsetWidth; // flush layout
|
|
|
|
|
|
|
|
is(JSON.stringify(received), "[2,1]", "add of existing listener is no-op");
|
|
|
|
received = [];
|
|
|
|
mql.addListener(listener1);
|
|
|
|
|
|
|
|
iframe.style.width = "100px";
|
|
|
|
subroot.offsetWidth; // flush layout
|
|
|
|
|
|
|
|
is(JSON.stringify(received), "[2,1]", "add of existing listener is no-op");
|
|
|
|
mql.removeListener(listener2);
|
|
|
|
received = [];
|
|
|
|
received_mql = [];
|
|
|
|
|
|
|
|
var mql2 = subwin.matchMedia("(min-width: 160px)");
|
|
|
|
mql2.addListener(listener1);
|
|
|
|
mql.addListener(listener2);
|
|
|
|
|
|
|
|
iframe.style.width = "200px";
|
|
|
|
subroot.offsetWidth; // flush layout
|
|
|
|
|
|
|
|
// mql (1, 2), mql2 (1)
|
|
|
|
is(JSON.stringify(received), "[1,2,1]",
|
|
|
|
"notification of lists in order created");
|
|
|
|
is(received_mql[0], mql,
|
|
|
|
"notification of lists in order created");
|
|
|
|
is(received_mql[1], mql,
|
|
|
|
"notification of lists in order created");
|
|
|
|
is(received_mql[2], mql2,
|
|
|
|
"notification of lists in order created");
|
|
|
|
received = [];
|
|
|
|
received_mql = [];
|
|
|
|
|
|
|
|
function removing_listener(mql) {
|
|
|
|
received.push(3);
|
|
|
|
received_mql.push(mql);
|
|
|
|
mql.removeListener(listener2);
|
|
|
|
mql2.removeListener(listener1);
|
|
|
|
}
|
|
|
|
|
|
|
|
mql.addListener(removing_listener);
|
|
|
|
mql.removeListener(listener2);
|
|
|
|
mql.addListener(listener2); // after removing_listener (3)
|
|
|
|
|
|
|
|
iframe.style.width = "100px";
|
|
|
|
subroot.offsetWidth; // flush layout
|
|
|
|
|
|
|
|
// mql(1, 3, 2) mql2(1)
|
|
|
|
is(JSON.stringify(received), "[1,3,2,1]",
|
|
|
|
"listeners still notified after removed if change was before");
|
|
|
|
is(received_mql[0], mql,
|
|
|
|
"notification order (removal tests)");
|
|
|
|
is(received_mql[1], mql,
|
|
|
|
"notification order (removal tests)");
|
|
|
|
is(received_mql[2], mql,
|
|
|
|
"notification order (removal tests)");
|
|
|
|
is(received_mql[3], mql2,
|
|
|
|
"notification order (removal tests)");
|
|
|
|
received = [];
|
|
|
|
received_mql = [];
|
|
|
|
|
|
|
|
iframe.style.width = "200px";
|
|
|
|
subroot.offsetWidth; // flush layout
|
|
|
|
|
|
|
|
// mql(1, 3)
|
|
|
|
is(JSON.stringify(received), "[1,3]",
|
|
|
|
"listeners not notified for changes after their removal");
|
|
|
|
is(received_mql[0], mql,
|
|
|
|
"notification order (removal tests)");
|
|
|
|
is(received_mql[1], mql,
|
|
|
|
"notification order (removal tests)");
|
|
|
|
})();
|
|
|
|
|
2012-02-29 20:47:55 -08:00
|
|
|
/* Bug 716751: null-dereference crash */
|
|
|
|
(function() {
|
|
|
|
iframe.style.width = "200px";
|
|
|
|
subroot.offsetWidth; // flush layout
|
|
|
|
|
|
|
|
var mql = subwin.matchMedia("(min-width: 150px)");
|
2013-12-16 06:03:34 -08:00
|
|
|
SimpleTest.doesThrow(function() {
|
|
|
|
mql.addListener(null);
|
|
|
|
}, "expected an exception");
|
2012-02-29 20:47:55 -08:00
|
|
|
|
|
|
|
iframe.style.width = "100px";
|
|
|
|
subroot.offsetWidth; // flush layout
|
|
|
|
// With the bug, we crash here. No need for test assertions.
|
|
|
|
|
2013-12-16 06:03:34 -08:00
|
|
|
SimpleTest.doesThrow(function() {
|
|
|
|
mql.removeListener(null);
|
|
|
|
}, "expected an exception");
|
|
|
|
SimpleTest.doesThrow(function() {
|
|
|
|
mql.removeListener(null);
|
|
|
|
}, "expected an exception");
|
2012-02-29 20:47:55 -08:00
|
|
|
})();
|
|
|
|
|
2012-07-07 21:41:27 -07:00
|
|
|
/* Bug 753777: test that things work in a freshly-created iframe */
|
|
|
|
(function() {
|
|
|
|
var iframe = document.createElement("iframe");
|
|
|
|
document.body.appendChild(iframe);
|
|
|
|
|
|
|
|
is(iframe.contentWindow.matchMedia("(min-width: 1px)").matches, true,
|
|
|
|
"(min-width: 1px) should match in newly-created iframe");
|
|
|
|
is(iframe.contentWindow.matchMedia("(max-width: 1px)").matches, false,
|
|
|
|
"(max-width: 1px) should not match in newly-created iframe");
|
|
|
|
|
|
|
|
document.body.removeChild(iframe);
|
|
|
|
})();
|
|
|
|
|
2012-02-29 20:47:55 -08:00
|
|
|
/* Bug 716751: listeners lost due to GC */
|
|
|
|
var gc_received = [];
|
|
|
|
(function() {
|
|
|
|
var received = [];
|
|
|
|
var listener1 = function(mql) {
|
|
|
|
gc_received.push(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
iframe.style.width = "200px";
|
|
|
|
subroot.offsetWidth; // flush layout
|
|
|
|
|
|
|
|
var mql = subwin.matchMedia("(min-width: 150px)");
|
|
|
|
mql.addListener(listener1);
|
|
|
|
is(JSON.stringify(gc_received), "[]", "GC test: before notification");
|
|
|
|
|
|
|
|
iframe.style.width = "100px";
|
|
|
|
subroot.offsetWidth; // flush layout
|
|
|
|
|
|
|
|
is(JSON.stringify(gc_received), "[1]", "GC test: after notification 1");
|
|
|
|
|
|
|
|
// Because of conservative GC, we need to go back to the event loop
|
|
|
|
// to GC properly.
|
|
|
|
setTimeout(step2, 0);
|
|
|
|
})();
|
|
|
|
|
|
|
|
function step2() {
|
|
|
|
SpecialPowers.DOMWindowUtils.garbageCollect();
|
|
|
|
|
|
|
|
iframe.style.width = "200px";
|
|
|
|
subroot.offsetWidth; // flush layout
|
|
|
|
|
|
|
|
is(JSON.stringify(gc_received), "[1,1]", "GC test: after notification 2");
|
|
|
|
|
|
|
|
SimpleTest.finish();
|
|
|
|
}
|
2011-04-21 20:17:31 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
</script>
|
|
|
|
</pre>
|
|
|
|
</body>
|
|
|
|
</html>
|