mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-21 20:15:17 +00:00
LibWeb: Invalidate document style when media rules are changed
This ensures that new media rules are always produce the correct result when evaluated.
This commit is contained in:
parent
34dae06dd8
commit
c6fc7aadba
4 changed files with 2110 additions and 0 deletions
|
@ -329,6 +329,7 @@ void CSSStyleSheet::remove_owning_document_or_shadow_root(DOM::Node& document_or
|
|||
|
||||
void CSSStyleSheet::invalidate_owners(DOM::StyleInvalidationReason reason)
|
||||
{
|
||||
m_did_match = {};
|
||||
for (auto& document_or_shadow_root : m_owning_documents_or_shadow_roots) {
|
||||
document_or_shadow_root->invalidate_style(reason);
|
||||
document_or_shadow_root->document().style_computer().invalidate_rule_cache();
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||
"http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html lang="en-US">
|
||||
<head>
|
||||
<title>Media Queries Test inner frame</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
|
||||
<meta http-equiv="Content-Style-Type" content="text/css">
|
||||
<style type="text/css" id="style" media="all">
|
||||
body { text-decoration: underline; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,740 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Media Queries Self-Contained Test Suite</title>
|
||||
<link rel="author" title="L. David Baron" href="https://dbaron.org/">
|
||||
<link rel="author" title="Anne van Kesteren" href="http://annevankesteren.nl/">
|
||||
<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
|
||||
<link rel="help" href="https://www.w3.org/TR/css3-mediaqueries/#media0">
|
||||
<script type="text/javascript" src="../../resources/testharness.js"></script>
|
||||
<script type="text/javascript" src="../../resources/testharnessreport.js"></script>
|
||||
</head>
|
||||
<body onload="run()">
|
||||
<div id=log></div>
|
||||
<iframe id="subdoc" src="support/media_queries_iframe.html"></iframe>
|
||||
<div id="content" style="display: none"></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
setup({ "explicit_done": true });
|
||||
|
||||
function run() {
|
||||
var subdoc = document.getElementById("subdoc").contentDocument;
|
||||
var subwin = document.getElementById("subdoc").contentWindow;
|
||||
var style = subdoc.getElementById("style");
|
||||
var iframe_style = document.getElementById("subdoc").style;
|
||||
var body_cs = subdoc.defaultView.getComputedStyle(subdoc.body, "");
|
||||
var testGroup = "";
|
||||
|
||||
function query_applies(q) {
|
||||
style.setAttribute("media", q);
|
||||
return body_cs.getPropertyValue("text-decoration-line") == "underline";
|
||||
}
|
||||
|
||||
function not(predicate) {
|
||||
return (...args) => !predicate(...args);
|
||||
}
|
||||
|
||||
function test_predicate(input, predicate, name) {
|
||||
test(() => {
|
||||
// lazily evaluate template string to avoid including device-specific data in test name
|
||||
var escaped = JSON.stringify(input);
|
||||
var evaled = eval("`" + escaped.substring(1, escaped.length - 1) + "`");
|
||||
// Also avoid an assert message for the same reason. (Relevant for
|
||||
// failing tests).
|
||||
assert_true(predicate(evaled))
|
||||
}, `${testGroup ? testGroup + ": " : ""}${name}: ${input}`);
|
||||
}
|
||||
|
||||
function should_apply(q) {
|
||||
test_predicate(q, query_applies, "should_apply");
|
||||
}
|
||||
|
||||
function should_not_apply(q) {
|
||||
test_predicate(q, not(query_applies), "should_not_apply");
|
||||
}
|
||||
|
||||
/*
|
||||
* Functions to test whether a query is parseable at all. (Should not
|
||||
* be used for parse errors within expressions.)
|
||||
*/
|
||||
var parse_test_style_element = document.createElement("style");
|
||||
parse_test_style_element.type = "text/css";
|
||||
parse_test_style_element.disabled = true; // for performance, hopefully
|
||||
var parse_test_style_text = document.createTextNode("");
|
||||
parse_test_style_element.appendChild(parse_test_style_text);
|
||||
document.getElementsByTagName("head")[0]
|
||||
.appendChild(parse_test_style_element);
|
||||
|
||||
function query_is_parseable(q) {
|
||||
parse_test_style_text.data = "@media screen, " + q + " {}";
|
||||
var sheet = parse_test_style_element.sheet; // XXX yikes, not live!
|
||||
if (sheet.cssRules.length == 1 &&
|
||||
sheet.cssRules[0].type == CSSRule.MEDIA_RULE)
|
||||
return sheet.cssRules[0].media.mediaText != "screen, not all";
|
||||
|
||||
assert_unreached(
|
||||
"unexpected result testing whether query " + q + " is parseable");
|
||||
}
|
||||
|
||||
function query_should_be_parseable(q) {
|
||||
test_predicate(q, query_is_parseable, "query_should_be_parseable");
|
||||
}
|
||||
|
||||
function query_should_not_be_parseable(q) {
|
||||
test_predicate(q, not(query_is_parseable), "query_should_not_be_parseable");
|
||||
}
|
||||
|
||||
/*
|
||||
* Functions to test whether a single media expression is "unknown" or not.
|
||||
*
|
||||
* https://drafts.csswg.org/mediaqueries-4/#evaluating
|
||||
*/
|
||||
|
||||
function expression_is_parseable(e) {
|
||||
return query_is_parseable(`(${e})`);
|
||||
}
|
||||
|
||||
function expression_is_known(e) {
|
||||
return query_applies(`(${e}), not all and (${e})`);
|
||||
}
|
||||
|
||||
function expression_should_be_known(e) {
|
||||
// We don't bother with expression_is_parseable here, because it must be parseable to be known
|
||||
test_predicate(e, expression_is_known, "expression_should_be_known");
|
||||
}
|
||||
|
||||
function expression_should_be_unknown(e) {
|
||||
test_predicate(e, expression_is_parseable, "expression_should_be_parseable");
|
||||
test_predicate(e, not(expression_is_known), "expression_should_be_unknown");
|
||||
}
|
||||
|
||||
// The no-type syntax doesn't mix with the not and only keywords.
|
||||
query_should_be_parseable("(orientation)");
|
||||
query_should_be_parseable("not (orientation)");
|
||||
expression_should_be_known("(orientation)");
|
||||
expression_should_be_known("not (orientation)");
|
||||
query_should_not_be_parseable("only (orientation)");
|
||||
query_should_be_parseable("all and (orientation)");
|
||||
query_should_be_parseable("not all and (orientation)");
|
||||
query_should_be_parseable("only all and (orientation)");
|
||||
|
||||
query_should_not_be_parseable("not not (orientation)");
|
||||
query_should_be_parseable("(orientation) and (orientation)");
|
||||
query_should_be_parseable("(orientation) or (orientation)");
|
||||
query_should_be_parseable("(orientation) or ((orientation) and ((orientation) or (orientation) or (not (orientation))))");
|
||||
expression_should_be_known("(orientation) and (orientation)");
|
||||
expression_should_be_known("(orientation) or (orientation)");
|
||||
expression_should_be_known("(orientation) or ((orientation) and ((orientation) or (orientation) or (not (orientation))))");
|
||||
|
||||
query_should_not_be_parseable("all and (orientation) or (orientation)");
|
||||
query_should_be_parseable("all and (orientation) and (orientation)");
|
||||
|
||||
query_should_not_be_parseable("(orientation) and (orientation) or (orientation)");
|
||||
query_should_not_be_parseable("(orientation) and not (orientation)");
|
||||
|
||||
var features = [ "width", "height", "device-width", "device-height" ];
|
||||
var separators = [ ":", ">", ">=", "=", "<=", "<" ];
|
||||
var feature;
|
||||
var i;
|
||||
for (i in features) {
|
||||
feature = features[i];
|
||||
expression_should_be_known(feature);
|
||||
expression_should_be_unknown("min-" + feature);
|
||||
expression_should_be_unknown("max-" + feature);
|
||||
for (let separator of separators) {
|
||||
expression_should_be_known(feature + " " + separator + " 0");
|
||||
expression_should_be_known(feature + " " + separator + " 0px");
|
||||
expression_should_be_known(feature + " " + separator + " 0em");
|
||||
expression_should_be_known(feature + " " + separator + " -0");
|
||||
expression_should_be_known(feature + " " + separator + " -0cm");
|
||||
expression_should_be_known(feature + " " + separator + " 1px");
|
||||
expression_should_be_known(feature + " " + separator + " 0.001mm");
|
||||
expression_should_be_known(feature + " " + separator + " 100000px");
|
||||
if (separator == ":") {
|
||||
expression_should_be_known("min-" + feature + " " + separator + " -0");
|
||||
expression_should_be_known("max-" + feature + " " + separator + " -0");
|
||||
} else {
|
||||
expression_should_be_unknown("min-" + feature + " " + separator + " -0");
|
||||
expression_should_be_unknown("max-" + feature + " " + separator + " -0");
|
||||
let multi_range = "0px " + separator + " " + feature + " " + separator + " 100000px"
|
||||
if (separator == "=") {
|
||||
expression_should_be_unknown(multi_range);
|
||||
} else {
|
||||
expression_should_be_known(multi_range);
|
||||
}
|
||||
}
|
||||
if (separator == ">=") {
|
||||
expression_should_be_unknown(feature + " > = 0px");
|
||||
} else if (separator == "<=") {
|
||||
expression_should_be_unknown(feature + " < = 0px");
|
||||
}
|
||||
|
||||
expression_should_be_known(feature + " " + separator + " -1px");
|
||||
if (separator == ":") {
|
||||
expression_should_be_known("min-" + feature + " " + separator + " -1px");
|
||||
expression_should_be_known("max-" + feature + " " + separator + " -1px");
|
||||
} else {
|
||||
expression_should_be_unknown("min-" + feature + " " + separator + " -1px");
|
||||
expression_should_be_unknown("max-" + feature + " " + separator + " -1px");
|
||||
}
|
||||
expression_should_be_known(feature + " " + separator + " -0.00001mm");
|
||||
expression_should_be_known(feature + " " + separator + " -100000em");
|
||||
|
||||
for (let separator2 of separators) {
|
||||
// https://drafts.csswg.org/mediaqueries-4/#typedef-mf-range
|
||||
if (separator[0] == separator2[0] && (separator[0] == '<' || separator[0] == '>')) {
|
||||
expression_should_be_known(`0px ${separator} ${feature} ${separator2} 0px`);
|
||||
} else {
|
||||
expression_should_be_unknown(`0px ${separator} ${feature} ${separator2} 0px`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var content_div = document.getElementById("content");
|
||||
content_div.style.font = "medium sans-serif";
|
||||
var em_size =
|
||||
getComputedStyle(content_div, "").fontSize.match(/^(\d+)px$/)[1];
|
||||
|
||||
// in this test, assume the common underlying implementation is correct
|
||||
var width_val = 117; // pick two not-too-round numbers
|
||||
var height_val = 76;
|
||||
iframe_style.width = width_val + "px";
|
||||
iframe_style.height = height_val + "px";
|
||||
var device_width = window.screen.width;
|
||||
var device_height = window.screen.height;
|
||||
features = {
|
||||
"width": width_val,
|
||||
"height": height_val,
|
||||
"device-width": device_width,
|
||||
"device-height": device_height
|
||||
};
|
||||
for (feature in features) {
|
||||
var value = features[feature];
|
||||
should_apply("all and (" + feature + ": ${value}px)");
|
||||
should_apply("all and (" + feature + " = ${value}px)");
|
||||
should_not_apply("all and (" + feature + ": ${value + 1}px)");
|
||||
should_not_apply("all and (" + feature + ": ${value - 1}px)");
|
||||
should_not_apply("all and (" + feature + " = ${value + 1}px)");
|
||||
should_not_apply("all and (" + feature + " = ${value - 1}px)");
|
||||
|
||||
should_apply("all and (min-" + feature + ": ${value}px)");
|
||||
should_not_apply("all and (min-" + feature + ": ${value + 1}px)");
|
||||
should_apply("all and (min-" + feature + ": ${value - 1}px)");
|
||||
should_apply("all and (max-" + feature + ": ${value}px)");
|
||||
should_apply("all and (max-" + feature + ": ${value + 1}px)");
|
||||
should_not_apply("all and (max-" + feature + ": ${value - 1}px)");
|
||||
should_not_apply("all and (min-" + feature + ": ${Math.ceil(value/em_size) + 1}em)");
|
||||
should_apply("all and (min-" + feature + ": ${Math.floor(value/em_size) - 1}em)");
|
||||
should_apply("all and (max-" + feature + ": ${Math.ceil(value/em_size) + 1}em)");
|
||||
should_not_apply("all and (max-" + feature + ": ${Math.floor(value/em_size) - 1}em)");
|
||||
|
||||
should_apply("(" + feature + " <= ${value}px)");
|
||||
should_apply("(" + feature + " >= ${value}px)");
|
||||
|
||||
should_apply("(0px < " + feature + " <= ${value}px)");
|
||||
should_apply("(${value}px >= " + feature + " > 0px)");
|
||||
|
||||
should_not_apply("(0px < " + feature + " < ${value}px)");
|
||||
should_not_apply("(${value}px > " + feature + " > 0px)");
|
||||
|
||||
should_not_apply("(" + feature + " < ${value}px)");
|
||||
should_not_apply("(" + feature + " > ${value}px)");
|
||||
|
||||
should_apply("(" + feature + " < ${value + 1}px)");
|
||||
should_apply("(" + feature + " <= ${value + 1}px)");
|
||||
should_not_apply("(" + feature + " > ${value + 1}px)");
|
||||
should_not_apply("(" + feature + " >= ${value + 1}px)");
|
||||
|
||||
should_apply("(" + feature + " > ${value - 1}px)");
|
||||
should_apply("(" + feature + " >= ${value - 1}px)");
|
||||
should_not_apply("(" + feature + " < ${value - 1}px)");
|
||||
should_not_apply("(" + feature + " <= ${value - 1}px)");
|
||||
|
||||
should_apply("(${value - 1}px < " + feature + ")");
|
||||
should_apply("(${value - 1}px <= " + feature + ")");
|
||||
should_not_apply("(${value - 1}px > " + feature + ")");
|
||||
should_not_apply("(${value - 1}px >= " + feature + ")");
|
||||
|
||||
should_apply("(${value - 1}px < " + feature + " < ${value + 1}px)");
|
||||
should_apply("(${value - 1}px < " + feature + " <= ${value}px)");
|
||||
should_apply("(${value}px <= " + feature + " < ${value + 1}px)");
|
||||
should_apply("(${value + 1}px > " + feature + " > ${value - 1}px)");
|
||||
should_apply("(${value + 1}px > " + feature + " >= ${value}px)");
|
||||
should_apply("(${value}px >= " + feature + " > ${value - 1}px)");
|
||||
should_not_apply("(${value}px > " + feature + " > ${value - 1}px)");
|
||||
should_not_apply("(${value + 1}px > " + feature + " > ${value}px)");
|
||||
}
|
||||
|
||||
iframe_style.width = "0";
|
||||
testGroup = "width = 0, height != 0";
|
||||
should_apply("all and (height)");
|
||||
should_not_apply("all and (width)");
|
||||
iframe_style.height = "0";
|
||||
testGroup = "width = 0, height = 0"
|
||||
should_not_apply("all and (height)");
|
||||
should_not_apply("all and (width)");
|
||||
should_apply("all and (device-height)");
|
||||
should_apply("all and (device-width)");
|
||||
iframe_style.width = width_val + "px";
|
||||
testGroup = "width != 0, height = 0";
|
||||
should_not_apply("all and (height)");
|
||||
should_apply("all and (width)");
|
||||
iframe_style.height = height_val + "px";
|
||||
testGroup = "width != 0, height != 0";
|
||||
should_apply("all and (height)");
|
||||
should_apply("all and (width)");
|
||||
testGroup = "";
|
||||
|
||||
testGroup = "ratio that reduces to 59/40";
|
||||
iframe_style.width = "236px";
|
||||
iframe_style.height = "160px";
|
||||
expression_should_be_known("orientation");
|
||||
expression_should_be_known("orientation: portrait");
|
||||
expression_should_be_known("orientation: landscape");
|
||||
expression_should_be_unknown("min-orientation");
|
||||
expression_should_be_unknown("min-orientation: portrait");
|
||||
expression_should_be_unknown("min-orientation: landscape");
|
||||
expression_should_be_unknown("max-orientation");
|
||||
expression_should_be_unknown("max-orientation: portrait");
|
||||
expression_should_be_unknown("max-orientation: landscape");
|
||||
should_apply("(orientation)");
|
||||
should_apply("(orientation: landscape)");
|
||||
should_not_apply("(orientation: portrait)");
|
||||
should_apply("not all and (orientation: portrait)");
|
||||
|
||||
testGroup = "ratio that reduces to 59/80";
|
||||
iframe_style.height = "320px";
|
||||
should_apply("(orientation)");
|
||||
should_not_apply("(orientation: landscape)");
|
||||
should_apply("not all and (orientation: landscape)");
|
||||
should_apply("(orientation: portrait)");
|
||||
testGroup = "";
|
||||
|
||||
should_apply("(aspect-ratio: 59/80)");
|
||||
should_not_apply("(aspect-ratio: 58/80)");
|
||||
should_not_apply("(aspect-ratio: 59/81)");
|
||||
should_not_apply("(aspect-ratio: 60/80)");
|
||||
should_not_apply("(aspect-ratio: 59/79)");
|
||||
should_apply("(aspect-ratio: 177/240)");
|
||||
should_apply("(aspect-ratio: 413/560)");
|
||||
should_apply("(aspect-ratio: 5900/8000)");
|
||||
should_not_apply("(aspect-ratio: 5901/8000)");
|
||||
should_not_apply("(aspect-ratio: 5899/8000)");
|
||||
should_not_apply("(aspect-ratio: 5900/8001)");
|
||||
should_not_apply("(aspect-ratio: 5900/7999)");
|
||||
should_apply("(aspect-ratio)");
|
||||
|
||||
should_apply("(min-aspect-ratio: 59/80)");
|
||||
should_apply("(min-aspect-ratio: 58/80)");
|
||||
should_apply("(min-aspect-ratio: 59/81)");
|
||||
should_not_apply("(min-aspect-ratio: 60/80)");
|
||||
should_not_apply("(min-aspect-ratio: 59/79)");
|
||||
expression_should_be_unknown("min-aspect-ratio");
|
||||
|
||||
should_apply("(max-aspect-ratio: 59/80)");
|
||||
should_not_apply("(max-aspect-ratio: 58/80)");
|
||||
should_not_apply("(max-aspect-ratio: 59/81)");
|
||||
should_apply("(max-aspect-ratio: 60/80)");
|
||||
should_apply("(max-aspect-ratio: 59/79)");
|
||||
expression_should_be_unknown("max-aspect-ratio");
|
||||
|
||||
var real_dar = device_width + "/" + device_height;
|
||||
var high_dar_1 = (device_width + 1) + "/" + device_height;
|
||||
var high_dar_2 = device_width + "/" + (device_height - 1);
|
||||
var low_dar_1 = (device_width - 1) + "/" + device_height;
|
||||
var low_dar_2 = device_width + "/" + (device_height + 1);
|
||||
should_apply("(device-aspect-ratio: ${real_dar})");
|
||||
should_apply("not all and (device-aspect-ratio: ${high_dar_1})");
|
||||
should_not_apply("all and (device-aspect-ratio: ${high_dar_2})");
|
||||
should_not_apply("all and (device-aspect-ratio: ${low_dar_1})");
|
||||
should_apply("not all and (device-aspect-ratio: ${low_dar_2})");
|
||||
should_apply("(device-aspect-ratio)");
|
||||
|
||||
should_apply("(min-device-aspect-ratio: ${real_dar})");
|
||||
should_not_apply("all and (min-device-aspect-ratio: ${high_dar_1})");
|
||||
should_apply("not all and (min-device-aspect-ratio: ${high_dar_2})");
|
||||
should_not_apply("not all and (min-device-aspect-ratio: ${low_dar_1})");
|
||||
should_apply("all and (min-device-aspect-ratio: ${low_dar_2})");
|
||||
expression_should_be_unknown("min-device-aspect-ratio");
|
||||
|
||||
should_apply("all and (max-device-aspect-ratio: ${real_dar})");
|
||||
should_apply("(max-device-aspect-ratio: ${high_dar_1})");
|
||||
should_apply("(max-device-aspect-ratio: ${high_dar_2})");
|
||||
should_not_apply("all and (max-device-aspect-ratio: ${low_dar_1})");
|
||||
should_apply("not all and (max-device-aspect-ratio: ${low_dar_2})");
|
||||
expression_should_be_unknown("max-device-aspect-ratio");
|
||||
|
||||
features = [ "max-aspect-ratio", "device-aspect-ratio" ];
|
||||
for (i in features) {
|
||||
feature = features[i];
|
||||
expression_should_be_known(feature + ": 1/1");
|
||||
expression_should_be_known(feature + ": 1 /1");
|
||||
expression_should_be_known(feature + ": 1 / \t\n1");
|
||||
expression_should_be_known(feature + ": 1/\r1");
|
||||
expression_should_be_known(feature + ": 1");
|
||||
expression_should_be_known(feature + ": 0.5");
|
||||
expression_should_be_known(feature + ": 1.0/1");
|
||||
expression_should_be_known(feature + ": 1/1.0");
|
||||
expression_should_be_known(feature + ": 1.0/1.0");
|
||||
expression_should_be_known(feature + ": 0/1");
|
||||
expression_should_be_known(feature + ": 1/0");
|
||||
expression_should_be_known(feature + ": 0/0");
|
||||
expression_should_be_unknown(feature + ": -1/1");
|
||||
expression_should_be_unknown(feature + ": 1/-1");
|
||||
expression_should_be_unknown(feature + ": -1/-1");
|
||||
expression_should_be_unknown(feature + ": invalid");
|
||||
expression_should_be_unknown(feature + ": 1 / invalid");
|
||||
expression_should_be_unknown(feature + ": 1 invalid");
|
||||
}
|
||||
|
||||
var is_monochrome = query_applies("all and (min-monochrome: 1)");
|
||||
var is_color = query_applies("all and (min-color: 1)");
|
||||
test(function() {
|
||||
assert_not_equals(is_monochrome, is_color, "should be either monochrome or color");
|
||||
}, "monochrome_and_color");
|
||||
|
||||
function depth_query(prefix, depth) {
|
||||
return "all and (" + prefix + (is_color ? "color" : "monochrome") +
|
||||
":" + depth + ")";
|
||||
}
|
||||
|
||||
var depth = 0;
|
||||
do {
|
||||
if (depth > 50) {
|
||||
break;
|
||||
}
|
||||
} while (query_applies(depth_query("min-", ++depth)));
|
||||
test(function() {
|
||||
assert_false(50 < depth);
|
||||
}, "find_depth");
|
||||
--depth;
|
||||
|
||||
should_apply(depth_query("", depth));
|
||||
should_not_apply(depth_query("", depth - 1));
|
||||
should_not_apply(depth_query("", depth + 1));
|
||||
should_apply(depth_query("max-", depth));
|
||||
should_not_apply(depth_query("max-", depth - 1));
|
||||
should_apply(depth_query("max-", depth + 1));
|
||||
|
||||
(is_color ? should_apply : should_not_apply)("all and (color)");
|
||||
expression_should_be_unknown("max-color");
|
||||
expression_should_be_unknown("min-color");
|
||||
(is_color ? should_not_apply : should_apply)("all and (monochrome)");
|
||||
expression_should_be_unknown("max-monochrome");
|
||||
expression_should_be_unknown("min-monochrome");
|
||||
(is_color ? should_apply : should_not_apply)("not all and (monochrome)");
|
||||
(is_color ? should_not_apply : should_apply)("not all and (color)");
|
||||
(is_color ? should_apply : should_not_apply)("only all and (color)");
|
||||
(is_color ? should_not_apply : should_apply)("only all and (monochrome)");
|
||||
|
||||
features = [ "color", "min-monochrome", "max-color-index" ];
|
||||
for (i in features) {
|
||||
feature = features[i];
|
||||
expression_should_be_known(feature + ": 1");
|
||||
expression_should_be_known(feature + ": 327");
|
||||
expression_should_be_known(feature + ": 0");
|
||||
expression_should_be_unknown(feature + ": 1.0");
|
||||
expression_should_be_known(feature + ": -1");
|
||||
expression_should_be_unknown(feature + ": 1/1");
|
||||
}
|
||||
|
||||
// Presume that we never support indexed color (at least not usefully
|
||||
// enough to call it indexed color).
|
||||
should_apply("(color-index: 0)");
|
||||
should_not_apply("(color-index: 1)");
|
||||
should_apply("(min-color-index: 0)");
|
||||
should_not_apply("(min-color-index: 1)");
|
||||
should_apply("(max-color-index: 0)");
|
||||
should_apply("(max-color-index: 1)");
|
||||
should_apply("(max-color-index: 157)");
|
||||
|
||||
features = [ "resolution", "min-resolution", "max-resolution" ];
|
||||
for (i in features) {
|
||||
feature = features[i];
|
||||
expression_should_be_known(feature + ": 3dpi");
|
||||
expression_should_be_known(feature + ":3dpi");
|
||||
expression_should_be_known(feature + ": 3.0dpi");
|
||||
expression_should_be_known(feature + ": 3.4dpi");
|
||||
expression_should_be_known(feature + "\t: 120dpcm");
|
||||
expression_should_be_known(feature + ": 1dppx");
|
||||
expression_should_be_known(feature + ": 1x");
|
||||
expression_should_be_known(feature + ": 1.5dppx");
|
||||
expression_should_be_known(feature + ": 1.5x");
|
||||
expression_should_be_known(feature + ": 2.0dppx");
|
||||
expression_should_be_known(feature + ": 0dpi");
|
||||
expression_should_be_known(feature + ": 0dppx");
|
||||
expression_should_be_known(feature + ": 0x");
|
||||
expression_should_be_known(feature + ": calc(6x / 2)");
|
||||
expression_should_be_unknown(feature + ": -3dpi");
|
||||
}
|
||||
|
||||
// Find the resolution using max-resolution
|
||||
var resolution = 0;
|
||||
do {
|
||||
++resolution;
|
||||
if (resolution > 10000) {
|
||||
break;
|
||||
}
|
||||
} while (!query_applies("(max-resolution: " + resolution + "dpi)"));
|
||||
test(function() {
|
||||
assert_false(10000 < resolution);
|
||||
}, "find_resolution");
|
||||
|
||||
// resolution should now be Math.ceil() of the actual resolution.
|
||||
var dpi_high;
|
||||
var dpi_low = resolution - 1;
|
||||
if (query_applies(`(min-resolution: ${resolution}dpi)`)) { // query_applies, so template literal!
|
||||
// It's exact!
|
||||
testGroup = "resolution is exact";
|
||||
should_apply("(resolution: ${resolution}dpi)");
|
||||
should_apply("(resolution: ${Math.floor(resolution/96)}dppx)");
|
||||
should_apply("(resolution: ${Math.floor(resolution/96)}x)");
|
||||
should_not_apply("(resolution: ${resolution + 1}dpi)");
|
||||
should_not_apply("(resolution: ${resolution - 1}dpi)");
|
||||
dpi_high = resolution + 1;
|
||||
} else {
|
||||
// We have no way to test resolution applying since it need not be
|
||||
// an integer.
|
||||
testGroup = "resolution is inexact";
|
||||
should_not_apply("(resolution: ${resolution}dpi)");
|
||||
should_not_apply("(resolution: ${resolution - 1}dpi)");
|
||||
dpi_high = resolution;
|
||||
}
|
||||
testGroup = "";
|
||||
|
||||
should_apply("(min-resolution: ${dpi_low}dpi)");
|
||||
should_not_apply("not all and (min-resolution: ${dpi_low}dpi)");
|
||||
should_apply("not all and (min-resolution: ${dpi_high}dpi)");
|
||||
should_not_apply("all and (min-resolution: ${dpi_high}dpi)");
|
||||
|
||||
// Test dpcm units based on what we computed in dpi.
|
||||
var dpcm_high = Math.ceil(dpi_high / 2.54);
|
||||
var dpcm_low = Math.floor(dpi_low / 2.54);
|
||||
should_apply("(min-resolution: ${dpcm_low}dpcm)");
|
||||
should_apply("(max-resolution: ${dpcm_high}dpcm)");
|
||||
should_not_apply("(max-resolution: ${dpcm_low}dpcm)");
|
||||
should_apply("not all and (min-resolution: ${dpcm_high}dpcm)");
|
||||
|
||||
expression_should_be_known("scan");
|
||||
expression_should_be_known("scan: progressive");
|
||||
expression_should_be_known("scan:interlace");
|
||||
expression_should_be_unknown("min-scan:interlace");
|
||||
expression_should_be_unknown("scan: 1");
|
||||
expression_should_be_unknown("max-scan");
|
||||
expression_should_be_unknown("max-scan: progressive");
|
||||
// Assume we don't support tv devices.
|
||||
should_not_apply("(scan)");
|
||||
should_not_apply("(scan: progressive)");
|
||||
should_not_apply("(scan: interlace)");
|
||||
should_apply("not all and (scan)");
|
||||
should_apply("not all and (scan: progressive)");
|
||||
should_apply("not all and (scan: interlace)");
|
||||
|
||||
expression_should_be_known("grid");
|
||||
expression_should_be_known("grid: 0");
|
||||
expression_should_be_known("grid: 1");
|
||||
expression_should_be_unknown("min-grid");
|
||||
expression_should_be_unknown("min-grid:0");
|
||||
expression_should_be_unknown("max-grid: 1");
|
||||
expression_should_be_unknown("grid: 2");
|
||||
expression_should_be_unknown("grid: -1");
|
||||
|
||||
// Assume we don't support grid devices
|
||||
should_not_apply("(grid)");
|
||||
should_apply("(grid: 0)");
|
||||
should_not_apply("(grid: 1)");
|
||||
should_not_apply("(grid: 2)");
|
||||
should_not_apply("(grid: -1)");
|
||||
|
||||
// Parsing tests
|
||||
// bug 454227
|
||||
should_apply("(orientation");
|
||||
should_not_apply("not all and (orientation");
|
||||
should_not_apply("(orientation:");
|
||||
should_not_apply("(orientation:)");
|
||||
should_not_apply("(orientation: )");
|
||||
should_apply("all,(orientation:");
|
||||
should_not_apply("(orientation:,all");
|
||||
should_apply("not all and (grid");
|
||||
should_not_apply("only all and (grid");
|
||||
should_not_apply("(grid");
|
||||
should_apply("all,(grid");
|
||||
should_not_apply("(grid,all");
|
||||
// bug 454226
|
||||
should_apply(",all");
|
||||
should_apply("all,");
|
||||
should_apply(",all,");
|
||||
should_apply("all,badmedium");
|
||||
should_apply("badmedium,all");
|
||||
should_not_apply(",badmedium,");
|
||||
should_apply("all,(badexpression)");
|
||||
should_apply("(badexpression),all");
|
||||
should_not_apply("(badexpression),badmedium");
|
||||
should_not_apply("badmedium,(badexpression)");
|
||||
should_apply("all,[badsyntax]");
|
||||
should_apply("[badsyntax],all");
|
||||
should_not_apply("badmedium,[badsyntax]");
|
||||
should_not_apply("[badsyntax],badmedium");
|
||||
|
||||
// Parsing tests based on Acid3
|
||||
query_should_not_be_parseable("all and color :");
|
||||
query_should_not_be_parseable("all and color : 1");
|
||||
should_not_apply("all and min-color : 1");
|
||||
should_not_apply("(bogus)");
|
||||
should_not_apply("not all and (bogus)")
|
||||
should_not_apply("only all and (bogus)")
|
||||
|
||||
// Parsing tests for overflow-block from mediaqueries-4
|
||||
expression_should_be_known("overflow-block")
|
||||
expression_should_be_known("overflow-block: none")
|
||||
expression_should_be_known("overflow-block: paged")
|
||||
expression_should_be_known("overflow-block: scroll")
|
||||
expression_should_be_unknown("overflow-block: optional-paged")
|
||||
expression_should_be_unknown("overflow-block: some-random-invalid-thing")
|
||||
|
||||
// Sanity check for overflow-block
|
||||
test(function() {
|
||||
var any_overflow_block = query_applies("(overflow-block)");
|
||||
var overflow_block_none = query_applies("(overflow-block: none)");
|
||||
assert_not_equals(any_overflow_block, overflow_block_none, "overflow-block should be equivalent to not (overflow-block: none)");
|
||||
}, "Sanity check for overflow-block");
|
||||
|
||||
// Parsing tests for overflow-inline from mediaqueries-4
|
||||
expression_should_be_known("overflow-inline")
|
||||
expression_should_be_known("overflow-inline: none")
|
||||
expression_should_be_known("overflow-inline: scroll")
|
||||
expression_should_be_unknown("overflow-inline: some-random-invalid-thing")
|
||||
|
||||
// Sanity check for overflow-inline
|
||||
test(function() {
|
||||
var any_overflow_inline = query_applies("(overflow-inline)");
|
||||
var overflow_inline_none = query_applies("(overflow-inline: none)");
|
||||
assert_not_equals(any_overflow_inline, overflow_inline_none, "overflow-inline should be equivalent to not (overflow-inline: none)");
|
||||
}, "Sanity check for overflow-inline");
|
||||
|
||||
// Parsing tests for update from mediaqueries-4
|
||||
expression_should_be_known("update")
|
||||
expression_should_be_known("update: none")
|
||||
expression_should_be_known("update: slow")
|
||||
expression_should_be_known("update: fast")
|
||||
expression_should_be_unknown("update: some-random-invalid-thing")
|
||||
|
||||
// Sanity check for update
|
||||
test(function() {
|
||||
var any_update = query_applies("(update)");
|
||||
var update_none = query_applies("(update: none)");
|
||||
assert_not_equals(any_update, update_none, "update should be equivalent to not (update: none)");
|
||||
}, "Sanity check for update");
|
||||
|
||||
// Parsing tests for interaction media features.
|
||||
expression_should_be_known("hover")
|
||||
expression_should_be_known("hover: hover")
|
||||
expression_should_be_known("hover: none")
|
||||
expression_should_be_known("any-hover")
|
||||
expression_should_be_known("any-hover: hover")
|
||||
expression_should_be_known("any-hover: none")
|
||||
|
||||
test(function() {
|
||||
assert_equals(query_applies("(hover)"), query_applies("(hover: hover)"));
|
||||
} , "(hover) == (hover: hover)");
|
||||
|
||||
test(function() {
|
||||
assert_not_equals(query_applies("(hover)"), query_applies("(hover: none)"));
|
||||
}, "(hover) == not (hover: none)");
|
||||
|
||||
test(function() {
|
||||
assert_equals(query_applies("(any-hover)"), query_applies("(any-hover: hover)"));
|
||||
}, "(any-hover) == (any-hover: hover)");
|
||||
|
||||
test(function() {
|
||||
assert_not_equals(query_applies("(any-hover)"), query_applies("(any-hover: none)"));
|
||||
}, "(any-hover) == not (any-hover: none)");
|
||||
|
||||
expression_should_be_known("pointer")
|
||||
expression_should_be_known("pointer: coarse")
|
||||
expression_should_be_known("pointer: fine")
|
||||
expression_should_be_known("pointer: none")
|
||||
expression_should_be_known("any-pointer")
|
||||
expression_should_be_known("any-pointer: coarse")
|
||||
expression_should_be_known("any-pointer: fine")
|
||||
expression_should_be_known("any-pointer: none")
|
||||
|
||||
test(function() {
|
||||
assert_equals(query_applies("(pointer)"),
|
||||
query_applies("(pointer: coarse)") || query_applies("(pointer: fine)"));
|
||||
}, "(pointer) == (pointer: coarse) or (pointer: fine)");
|
||||
|
||||
test(function() {
|
||||
assert_not_equals(query_applies("(pointer)"),
|
||||
query_applies("(pointer: none)"));
|
||||
}, "(pointer) == not (pointer: none)");
|
||||
|
||||
test(function() {
|
||||
assert_equals(query_applies("(any-pointer)"),
|
||||
query_applies("(any-pointer: coarse)") || query_applies("(any-pointer: fine)"));
|
||||
}, "(any-pointer) == (any-pointer: coarse) or (any-pointer: fine)");
|
||||
|
||||
test(function() {
|
||||
assert_not_equals(query_applies("(any-pointer)"),
|
||||
query_applies("(any-pointer: none)"));
|
||||
}, "(any-pointer) == not (any-pointer: none)");
|
||||
|
||||
iframe_style.width = '100px';
|
||||
iframe_style.height = '0px';
|
||||
|
||||
testGroup = "'or' keyword"
|
||||
should_not_apply("(height) or (height)");
|
||||
should_apply("(width) or (height)");
|
||||
should_apply("(height) or (width)");
|
||||
should_apply("(height) or (width) or (height)");
|
||||
query_should_not_be_parseable("screen or (width)");
|
||||
query_should_not_be_parseable("screen and (width) or (height)");
|
||||
|
||||
testGroup = "nesting"
|
||||
should_not_apply("((height))");
|
||||
should_apply("((width))");
|
||||
should_apply("(((((width)))))");
|
||||
should_apply("(((((width");
|
||||
|
||||
testGroup = "'not' keyword"
|
||||
should_not_apply("not (width)");
|
||||
should_apply("not (height)");
|
||||
should_apply("not ((width) and (height))");
|
||||
should_not_apply("not ((width) or (height))");
|
||||
should_not_apply("not ((width) and (not (height)))");
|
||||
query_should_not_be_parseable("not (width) and not (height)");
|
||||
query_should_not_be_parseable("not not (width)");
|
||||
query_should_be_parseable("not unknown(width) ");
|
||||
|
||||
testGroup = "three-valued logic"
|
||||
should_not_apply("(unknown)");
|
||||
should_not_apply("not (unknown)");
|
||||
should_not_apply("((unknown) and (width))");
|
||||
should_not_apply("not ((unknown) and (width))");
|
||||
should_not_apply("((unknown) and (height))");
|
||||
should_apply("not ((unknown) and (height))");
|
||||
should_apply("((unknown) or (width))");
|
||||
should_not_apply("not ((unknown) or (width))");
|
||||
should_not_apply("((unknown) or (height))");
|
||||
should_not_apply("not ((unknown) or (height))");
|
||||
should_apply("(width) or (not ((unknown) and (width)))");
|
||||
should_not_apply("(width) and (not ((unknown) and (width)))");
|
||||
should_apply("(width) or (not ((unknown) or (width)))");
|
||||
should_not_apply("(width) and (not ((unknown) or (width)))");
|
||||
should_apply("(width) or (not ((unknown) and (height)))");
|
||||
should_apply("(width) and (not ((unknown) and (height)))");
|
||||
should_apply("(width) or (not ((unknown) or (height)))");
|
||||
should_not_apply("(width) and (not ((unknown) or (height)))");
|
||||
should_not_apply("unknown(width)");
|
||||
should_not_apply("not unknown(width)");
|
||||
should_apply("not (unknown(width) and (height))");
|
||||
should_not_apply("not (unknown(width) or (height))");
|
||||
|
||||
testGroup = ""
|
||||
done();
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Reference in a new issue