mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Auto merge of #13453 - metajack:media-query-list, r=jdm
Implement matchMedia and MediaQueryList <!-- Please describe your changes on the following line: --> --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [ ] These changes fix #13376 (github issue number if applicable). <!-- Either: --> - [x] There are tests for these changes OR - [ ] These changes do not require tests because _____ <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> Fixes #13376. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/13453) <!-- Reviewable:end -->
This commit is contained in:
commit
6ef46ab9e4
22 changed files with 500 additions and 20 deletions
|
@ -6,6 +6,7 @@ use app_units::Au;
|
|||
use cssparser::{Parser, SourcePosition};
|
||||
use euclid::size::TypedSize2D;
|
||||
use std::borrow::ToOwned;
|
||||
use string_cache::Atom;
|
||||
use style::error_reporting::ParseErrorReporter;
|
||||
use style::media_queries::*;
|
||||
use style::parser::ParserContextExtraData;
|
||||
|
@ -126,7 +127,7 @@ fn test_mq_unknown() {
|
|||
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == None, css.to_owned());
|
||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Unknown), css.to_owned());
|
||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Unknown(Atom::from("fridge"))), css.to_owned());
|
||||
assert!(q.expressions.len() == 0, css.to_owned());
|
||||
});
|
||||
|
||||
|
@ -134,7 +135,7 @@ fn test_mq_unknown() {
|
|||
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == Some(Qualifier::Only), css.to_owned());
|
||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Unknown), css.to_owned());
|
||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Unknown(Atom::from("glass"))), css.to_owned());
|
||||
assert!(q.expressions.len() == 0, css.to_owned());
|
||||
});
|
||||
|
||||
|
@ -142,7 +143,7 @@ fn test_mq_unknown() {
|
|||
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == Some(Qualifier::Not), css.to_owned());
|
||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Unknown), css.to_owned());
|
||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Unknown(Atom::from("wood"))), css.to_owned());
|
||||
assert!(q.expressions.len() == 0, css.to_owned());
|
||||
});
|
||||
}
|
||||
|
@ -247,7 +248,7 @@ fn test_mq_expressions() {
|
|||
assert!(list.media_queries.len() == 1, css.to_owned());
|
||||
let q = &list.media_queries[0];
|
||||
assert!(q.qualifier == None, css.to_owned());
|
||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Unknown), css.to_owned());
|
||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Unknown(Atom::from("fridge"))), css.to_owned());
|
||||
assert!(q.expressions.len() == 1, css.to_owned());
|
||||
match q.expressions[0] {
|
||||
Expression::Width(Range::Max(w)) => assert!(w == specified::Length::Absolute(Au::from_px(52))),
|
||||
|
|
|
@ -3,6 +3,3 @@
|
|||
[window_inherited_functions]
|
||||
expected: FAIL
|
||||
|
||||
[window_functions]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -24,9 +24,6 @@
|
|||
[Window method: getSelection]
|
||||
expected: FAIL
|
||||
|
||||
[Window method: matchMedia]
|
||||
expected: FAIL
|
||||
|
||||
[Window readonly attribute: applicationCache]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -6566,6 +6566,12 @@
|
|||
"url": "/_mozilla/css/float_relative_to_position.html"
|
||||
}
|
||||
],
|
||||
"css/matchMedia.html": [
|
||||
{
|
||||
"path": "css/matchMedia.html",
|
||||
"url": "/_mozilla/css/matchMedia.html"
|
||||
}
|
||||
],
|
||||
"css/media_calc_crash.html": [
|
||||
{
|
||||
"path": "css/media_calc_crash.html",
|
||||
|
|
15
tests/wpt/mozilla/meta/css/matchMedia.html.ini
Normal file
15
tests/wpt/mozilla/meta/css/matchMedia.html.ini
Normal file
|
@ -0,0 +1,15 @@
|
|||
[matchMedia.html]
|
||||
type: testharness
|
||||
expected: OK
|
||||
|
||||
[window.matchMedia exists]
|
||||
expected: FAIL
|
||||
|
||||
[MediaQueryList.matches for "(min-aspect-ratio: 1/1)"]
|
||||
expected: FAIL
|
||||
|
||||
[MediaQueryList.matches for "(width: 200px)"]
|
||||
expected: FAIL
|
||||
|
||||
[Resize iframe from 200x100 to 200x50, then to 100x50]
|
||||
expected: FAIL
|
1
tests/wpt/mozilla/tests/css/blank.html
Normal file
1
tests/wpt/mozilla/tests/css/blank.html
Normal file
|
@ -0,0 +1 @@
|
|||
<!--intentionally blank-->
|
188
tests/wpt/mozilla/tests/css/matchMedia.html
Normal file
188
tests/wpt/mozilla/tests/css/matchMedia.html
Normal file
|
@ -0,0 +1,188 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>CSS Test: CSSOM View matchMedia and MediaQueryList</title>
|
||||
<link rel="author" title="Rune Lillesveen" href="mailto:rune@opera.com">
|
||||
<link rel="help" href="http://www.w3.org/TR/cssom-view/#dom-window-matchmedia">
|
||||
<link rel="help" href="http://www.w3.org/TR/cssom-view/#the-mediaquerylist-interface">
|
||||
<link rel="help" href="http://www.w3.org/TR/cssom-1/#serializing-media-queries">
|
||||
<meta name="flags" content="dom">
|
||||
<script src="/resources/testharness.js" type="text/javascript"></script>
|
||||
<script src="/resources/testharnessreport.js" type="text/javascript"></script>
|
||||
<style type="text/css">
|
||||
iframe { border: none; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>Test not run - javascript required.</noscript>
|
||||
<div id="log"></div>
|
||||
<iframe width="200" height="100" src="blank.html"></iframe>
|
||||
<script type="text/javascript">
|
||||
function reflow(doc) {
|
||||
doc.body.offsetWidth;
|
||||
}
|
||||
|
||||
var iframe = document.querySelector("iframe");
|
||||
iframe.onload = function(){
|
||||
var iframe_window = iframe.contentWindow;
|
||||
|
||||
reflow(iframe_window.document);
|
||||
|
||||
test(function(){
|
||||
assert_inherits(window, "matchMedia");
|
||||
}, "window.matchMedia exists");
|
||||
|
||||
test(function(){
|
||||
assert_true(window.matchMedia instanceof Function, "FATAL ERROR: The window.matchMedia function is not present. The rest of the testsuite will fail to run.");
|
||||
}, "window.matchMedia is a Function");
|
||||
|
||||
var mql, mql1, mql2, mql3;
|
||||
|
||||
test(function(){
|
||||
mql = window.matchMedia("all");
|
||||
assert_true(mql instanceof MediaQueryList, "matchMedia(\"all\") returned MediaQueryList object.");
|
||||
}, "window.matchMedia(\"all\")");
|
||||
|
||||
test(function(){
|
||||
assert_idl_attribute(mql, "media", "Check that MediaQueryList.media exists.");
|
||||
}, "MediaQueryList.media exists");
|
||||
|
||||
test(function(){
|
||||
assert_readonly(mql, "media", "Check that MediaQueryList.media is readonly.");
|
||||
}, "MediaQueryList.media is readonly");
|
||||
|
||||
test(function(){
|
||||
assert_equals(mql.media, "all");
|
||||
}, "MediaQueryList.media for \"all\"");
|
||||
|
||||
test(function(){
|
||||
assert_idl_attribute(mql, "matches", "Check that MediaQueryList.matches exists.");
|
||||
}, "MediaQueryList.matches exists");
|
||||
|
||||
test(function(){
|
||||
assert_readonly(mql, "matches", "Check that MediaQueryList.matches is readonly.");
|
||||
}, "MediaQueryList.matches is readonly");
|
||||
|
||||
test(function(){
|
||||
assert_true(mql.matches);
|
||||
}, "MediaQueryList.matches for \"all\"");
|
||||
|
||||
test(function(){
|
||||
assert_inherits(mql, "addListener");
|
||||
}, "MediaQueryList.addListener exists");
|
||||
|
||||
test(function(){
|
||||
assert_true(mql.addListener instanceof Function);
|
||||
}, "MediaQueryList.addListener is a Function");
|
||||
|
||||
test(function(){
|
||||
assert_inherits(mql, "removeListener");
|
||||
}, "MediaQueryList.removeListener exists");
|
||||
|
||||
test(function(){
|
||||
assert_true(mql.removeListener instanceof Function);
|
||||
}, "MediaQueryList.removeListener is a Function");
|
||||
|
||||
test(function(){
|
||||
mql = window.matchMedia("::");
|
||||
assert_true(mql instanceof MediaQueryList, "window.matchMedia(\"::\") returned MediaQueryList object.");
|
||||
assert_equals(mql.media, "not all", "MediaQueryList.media serialized as \"not all\" from original string with syntax error.");
|
||||
}, "MediaQueryList.media syntax error");
|
||||
|
||||
test(function(){
|
||||
assert_false(mql.matches);
|
||||
}, "MediaQueryList.matches for \"not all\"");
|
||||
|
||||
test(function(){
|
||||
mql = iframe_window.matchMedia("(max-width: 199px), all and (min-width: 200px)");
|
||||
assert_equals(mql.media, "(max-width: 199px), (min-width: 200px)");
|
||||
assert_true(mql.matches);
|
||||
}, "MediaQueryList.matches for \"(max-width: 199px), all and (min-width: 200px)\"")
|
||||
|
||||
test(function(){
|
||||
mql = iframe_window.matchMedia("(min-aspect-ratio: 1/1)");
|
||||
assert_true(mql.matches);
|
||||
}, "MediaQueryList.matches for \"(min-aspect-ratio: 1/1)\"");
|
||||
|
||||
test(function(){
|
||||
mql = iframe_window.matchMedia("(width: 200px)");
|
||||
assert_true(mql.matches);
|
||||
}, "MediaQueryList.matches for \"(width: 200px)\"");
|
||||
|
||||
test(function(){
|
||||
mql1 = iframe_window.matchMedia("(max-height: 50px)");
|
||||
assert_false(mql1.matches);
|
||||
}, "MediaQueryList.matches for \"(max-height: 50px)\"");
|
||||
|
||||
test(function(){
|
||||
mql2 = iframe_window.matchMedia("(min-width: 150px)");
|
||||
assert_true(mql2.matches);
|
||||
}, "MediaQueryList.matches for \"(min-width: 150px)\"");
|
||||
|
||||
var resizeTest = async_test("Resize iframe from 200x100 to 200x50, then to 100x50");
|
||||
var listenerOrderTest = async_test("Listeners are called in the order which they have been added");
|
||||
var duplicateListenerTest = async_test("Listener added twice is only called once.");
|
||||
|
||||
window.onload = function(){
|
||||
|
||||
var rmListener = function(x){
|
||||
resizeTest.step(function(){
|
||||
assert_unreached("removeListener was not successful.");
|
||||
});
|
||||
};
|
||||
|
||||
var dupListener = function(x){
|
||||
duplicateListenerTest.step(function(){
|
||||
assert_false(mql1.dupListenerCalled, "Check that this listener has not been called before.");
|
||||
mql1.dupListenerCalled = true;
|
||||
});
|
||||
};
|
||||
|
||||
mql1.firstListenerCalled = false;
|
||||
mql1.dupListenerCalled = false;
|
||||
// Add listener twice and remove it below. Should not be called.
|
||||
mql1.addListener(rmListener);
|
||||
mql1.addListener(rmListener);
|
||||
// Add listener twice. Should only be called once.
|
||||
mql1.addListener(dupListener);
|
||||
mql1.addListener(dupListener);
|
||||
|
||||
mql1.addListener(function(x){
|
||||
resizeTest.step(function(){
|
||||
assert_equals(x, mql1, "Check that the MediaQueryList passed to the handler is the same that addListener was invoked on.");
|
||||
assert_true(x.matches, "(max-height: 50px) should now pass.");
|
||||
assert_true(mql2.matches, "(min-width: 150px) should still pass.");
|
||||
iframe.width = "100";
|
||||
});
|
||||
|
||||
listenerOrderTest.step(function(){
|
||||
assert_false(mql1.firstListenerCalled, "Check that this listener is only called once.");
|
||||
mql1.firstListenerCalled = true;
|
||||
});
|
||||
});
|
||||
|
||||
mql1.addListener(function(x){
|
||||
listenerOrderTest.step(function(){
|
||||
assert_true(mql1.firstListenerCalled, "Check that the listener added last is called last.");
|
||||
});
|
||||
listenerOrderTest.done();
|
||||
});
|
||||
|
||||
mql1.removeListener(rmListener);
|
||||
|
||||
mql2.addListener(function(x){
|
||||
duplicateListenerTest.done();
|
||||
resizeTest.step(function(){
|
||||
assert_equals(x, mql2, "Check that the MediaQueryList passed to the handler is the same that addListener was invoked on.");
|
||||
assert_true(mql1.matches, "(max-height: 50px) should still pass.");
|
||||
assert_false(x.matches, "(min-width: 150px) should now fail.");
|
||||
});
|
||||
resizeTest.done();
|
||||
});
|
||||
|
||||
iframe.height = "50";
|
||||
};
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -128,6 +128,7 @@ test_interfaces([
|
|||
"KeyboardEvent",
|
||||
"Location",
|
||||
"MediaError",
|
||||
"MediaQueryList",
|
||||
"MessageEvent",
|
||||
"MimeType",
|
||||
"MimeTypeArray",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue