function getScreenPixelsPerCSSPixel() {
return window.devicePixelRatio;
}
function run() { iframe = document.getElementById("subdoc"); var subdoc = iframe.contentDocument; var subwin = iframe.contentWindow; varstyle = subdoc.getElementById("style"); var iframe_style = iframe.style; var body_cs = subdoc.defaultView.getComputedStyle(subdoc.body);
function query_applies(q) { style.setAttribute("media", q);
return body_cs.getPropertyValue("text-decoration-line") == "underline";
}
function should_apply(q) {
ok(query_applies(q), q + " should apply");
test_serialization(q, true, true);
}
function should_not_apply(q) {
ok(!query_applies(q), q + " should not apply");
test_serialization(q, true, false);
}
/* for queries that are parseable standalone but not within CSS */
function should_apply_unbalanced(q) {
ok(query_applies(q), q + " should apply");
}
/* for queries that are parseable standalone but not within CSS */
function should_not_apply_unbalanced(q) {
ok(!query_applies(q), q + " 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";
ok(false, "unexpected result testing whether query " + q + " is parseable");
return true; // doesn't matter, we already failed
}
function query_should_be_parseable(q) {
ok(query_is_parseable(q), "query " + q + " should be parseable");
test_serialization(q, false, false);
}
function query_should_not_be_parseable(q) {
ok(!query_is_parseable(q), "query " + q + " should not be parseable");
}
function expression_should_be_known(e) {
should_apply(`(${e}) or (not (${e}))`);
}
function expression_should_not_be_known(e) {
should_not_apply(`(${e}) or (not (${e}))`);
}
// Helper to share code between -moz & -webkit device-pixel-ratio versions:
function test_device_pixel_ratio(equal_name, min_name, max_name) { var real_dpr = 1.0 * getScreenPixelsPerCSSPixel(); var high_dpr = 1.1 * getScreenPixelsPerCSSPixel(); var low_dpr = 0.9 * getScreenPixelsPerCSSPixel();
should_apply("all and (" + max_name + ": " + real_dpr + ")");
should_apply("all and (" + min_name + ": " + real_dpr + ")");
should_not_apply("not all and (" + max_name + ": " + real_dpr + ")");
should_not_apply("not all and (" + min_name + ": " + real_dpr + ")");
should_apply("all and (" + min_name + ": " + low_dpr + ")");
should_apply("all and (" + max_name + ": " + high_dpr + ")");
should_not_apply("all and (" + max_name + ": " + low_dpr + ")");
should_not_apply("all and (" + min_name + ": " + high_dpr + ")");
should_apply("not all and (" + max_name + ": " + low_dpr + ")");
should_apply("not all and (" + min_name + ": " + high_dpr + ")");
should_apply("(" + equal_name + ": " + real_dpr + ")");
should_not_apply("(" + equal_name + ": " + high_dpr + ")");
should_not_apply("(" + equal_name + ": " + low_dpr + ")");
should_apply("(" + equal_name + ")");
expression_should_not_be_known(min_name);
expression_should_not_be_known(max_name);
}
function test_serialization(q, test_application, expected_to_apply) { style.setAttribute("media", q); var ser1 = style.sheet.media.mediaText;
isnot(ser1, "", "serialization of '" + q + "' should not be empty"); style.setAttribute("media", ser1); var ser2 = style.sheet.media.mediaText;
is(ser2, ser1, "parse+serialize of '" + q + "' should be idempotent");
if (test_application) {
let applies = body_cs.getPropertyValue("text-decoration-line") == "underline";
is(applies, expected_to_apply, "Media query '" + q + "' should " + (expected_to_apply ? "" : "NOT ") + "apply after serialize + reparse");
}
// Test cloning var sheet = "@media " + q + " { body { text-decoration: underline } }" var sheeturl = "data:text/css," + escape(sheet); varlink = ""'>"; var htmldoc = "" + link + link + "";
post_clone_test(htmldoc, function() { var clonedoc = iframe.contentDocument; var clonewin = iframe.contentWindow; var links = clonedoc.getElementsByTagName("link");
// cause a clone var clonedsheet = links[1].sheet;
clonedsheet.insertRule("#nonexistent { color: purple}", 1);
// remove the uncloned sheet
links[0].remove();
var ser3 = clonedsheet.cssRules[0].media.mediaText;
is(ser3, ser1, "cloning query '" + q + "' should not change " + "serialization");
if (test_application) {
let applies = clonewin.getComputedStyle(clonedoc.body).
textDecorationLine == "underline";
is(applies, expected_to_apply, "Media query '" + q + "' should " + (expected_to_apply ? "" : "NOT ") + "apply after cloning");
}
});
}
// The no-type syntax doesn't mix with the not and only keywords.
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)");
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)");
query_should_be_parseable("(-moz-device-orientation)");
query_should_be_parseable("not (-moz-device-orientation)");
query_should_not_be_parseable("only (-moz-device-orientation)");
query_should_be_parseable("all and (-moz-device-orientation)");
query_should_be_parseable("not all and (-moz-device-orientation)");
query_should_be_parseable("only all and (-moz-device-orientation)");
// Test that the 'not', 'only', 'and', and 'or' keywords are not
// allowed as media types.
query_should_not_be_parseable("not");
query_should_not_be_parseable("and");
query_should_not_be_parseable("or");
query_should_not_be_parseable("only");
query_should_be_parseable("unknowntype");
query_should_not_be_parseable("not not");
query_should_not_be_parseable("not and");
query_should_not_be_parseable("not or");
query_should_not_be_parseable("not only");
query_should_be_parseable("not unknowntype");
query_should_not_be_parseable("only not");
query_should_not_be_parseable("only and");
query_should_not_be_parseable("only or");
query_should_not_be_parseable("only only");
query_should_be_parseable("only unknowntype");
query_should_not_be_parseable("not and (width)");
query_should_not_be_parseable("and and (width)");
query_should_not_be_parseable("or and (width)");
query_should_not_be_parseable("only and (width)");
query_should_be_parseable("unknowntype and (width)");
query_should_not_be_parseable("not not and (width)");
query_should_not_be_parseable("not and and (width)");
query_should_not_be_parseable("not or and (width)");
query_should_not_be_parseable("not only and (width)");
query_should_be_parseable("not unknowntype and (width)");
query_should_not_be_parseable("only not and (width)");
query_should_not_be_parseable("only and and (width)");
query_should_not_be_parseable("only or and (width)");
query_should_not_be_parseable("only only and (width)");
query_should_be_parseable("only unknowntype and (width)");
var features = [ "width", "height", "device-width", "device-height" ]; var separators = [ ":", ">", ">=", "=", "<=", "<" ];
// determine the actual configuration of the screen and test against it var device_orientation = (device_width > device_height) ? "landscape" : "portrait"; var not_device_orientation = (device_orientation == "landscape") ? "portrait" : "landscape";
should_apply("(-moz-device-orientation)");
should_apply("(-moz-device-orientation: " + device_orientation + ")");
should_not_apply("(-moz-device-orientation: " + not_device_orientation + ")");
should_apply("not all and (-moz-device-orientation: " + not_device_orientation + ")");
// Test "unreasonable", but still valid aspect ratios, such as aspect ratios with negative numbers,
// and zeros, and with numbers near 2^32 and 2^64 (to check overflow).
should_not_apply("(aspect-ratio: 0/1)");
should_not_apply("(aspect-ratio: 1/0)");
should_not_apply("(aspect-ratio: -1/1)");
should_not_apply("(aspect-ratio: 1/-1)");
should_not_apply("(aspect-ratio: -1/-1)");
should_not_apply("(aspect-ratio: -59/-80)");
should_not_apply("(aspect-ratio: 4294967295/4294967295)");
should_not_apply("(aspect-ratio: 4294967297/4294967297)");
should_not_apply("(aspect-ratio: 18446744073709560000/18446744073709560000)");
// Test min and max aspect ratios.
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_not_be_known("min-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_not_be_known("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_not_be_known("max-device-aspect-ratio");
// Tests for -moz- & -webkit versions of "device-pixel-ratio"
// (Note that the vendor prefixes go in different places.)
test_device_pixel_ratio("-moz-device-pixel-ratio", "min--moz-device-pixel-ratio", "max--moz-device-pixel-ratio");
test_device_pixel_ratio("-webkit-device-pixel-ratio", "-webkit-min-device-pixel-ratio", "-webkit-max-device-pixel-ratio");
// Make sure that we don't accidentally start accepting *unprefixed*
// "device-pixel-ratio" expressions:
expression_should_be_known("-webkit-device-pixel-ratio: 1.0");
expression_should_not_be_known("device-pixel-ratio: 1.0");
expression_should_be_known("-webkit-min-device-pixel-ratio: 1.0");
expression_should_not_be_known("min-device-pixel-ratio: 1.0");
expression_should_be_known("-webkit-max-device-pixel-ratio: 1.0");
expression_should_not_be_known("max-device-pixel-ratio: 1.0");
var is_monochrome = query_applies("all and (min-monochrome: 1)");
test_serialization("all and (min-monochrome: 1)", true, is_monochrome); var is_color = query_applies("all and (min-color: 1)");
test_serialization("all and (min-color: 1)", true, is_color);
isnot(is_monochrome, is_color, "should be either monochrome or color");
function depth_query(prefix, depth) {
return "all and (" + prefix + (is_color ? "color" : "monochrome") + ":" + depth + ")";
}
var depth = 0;
do {
if (depth > 50) {
ok(false, "breaking from loop, depth > 50");
break;
}
} while (query_applies(depth_query("min-", ++depth)));
--depth;
(is_color ? should_apply : should_not_apply)("all and (color)");
expression_should_not_be_known("max-color");
expression_should_not_be_known("min-color");
(is_color ? should_not_apply : should_apply)("all and (monochrome)");
expression_should_not_be_known("max-monochrome");
expression_should_not_be_known("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_known(feature + ": -1");
expression_should_not_be_known(feature + ": 1.0");
expression_should_not_be_known(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)");
// Find the resolution using max-resolution var resolution = 0;
do {
++resolution;
if (resolution > 10000) {
ok(false, "resolution greater than 10000dpi???");
break;
}
} while (!query_applies("(max-resolution: " + resolution + "dpi)"));
// 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)")) {
// It's 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.
should_not_apply("(resolution: " + resolution + "dpi)");
should_not_apply("(resolution: " + (resolution - 1) + "dpi)");
dpi_high = resolution;
}
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_not_be_known("min-scan:interlace");
expression_should_not_be_known("scan: 1");
expression_should_not_be_known("max-scan");
expression_should_not_be_known("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)");
// OpenType SVG media features
expression_should_not_be_known("(-moz-is-glyph)");
expression_should_not_be_known("not (-moz-is-glyph)");
expression_should_not_be_known("only (-moz-is-glyph)");
expression_should_not_be_known("all and (-moz-is-glyph)");
expression_should_not_be_known("not all and (-moz-is-glyph)");
expression_should_not_be_known("only all and (-moz-is-glyph)");
expression_should_not_be_known("(-moz-is-glyph:0)");
expression_should_not_be_known("not (-moz-is-glyph:0)");
expression_should_not_be_known("only (-moz-is-glyph:0)");
expression_should_not_be_known("all and (-moz-is-glyph:0)");
expression_should_not_be_known("not all and (-moz-is-glyph:0)");
expression_should_not_be_known("only all and (-moz-is-glyph:0)");
expression_should_not_be_known("(-moz-is-glyph:1)");
expression_should_not_be_known("not (-moz-is-glyph:1)");
expression_should_not_be_known("only (-moz-is-glyph:1)");
expression_should_not_be_known("all and (-moz-is-glyph:1)");
expression_should_not_be_known("not all and (-moz-is-glyph:1)");
expression_should_not_be_known("only all and (-moz-is-glyph:1)");
should_not_apply("not all and (-moz-is-glyph)");
should_not_apply("(-moz-is-glyph:0)");
should_not_apply("not all and (-moz-is-glyph:1)");
should_not_apply("only all and (-moz-is-glyph:0)");
should_not_apply("(-moz-is-glyph)");
should_not_apply("(-moz-is-glyph:1)");
should_not_apply("not all and (-moz-is-glyph:0)");
should_not_apply("only all and (-moz-is-glyph:1)");
/*
* The cloning tests have to post tests that wait for onload. However,
* we also make a bunch of state changes during the tests above. So we
* always change state using the change_state call, with both makes the
* change immediately and posts an item in the same queue so that we
* make the same state change again later.
*/
var posted_items = [];
function change_state(func)
{
func();
posted_items.push({state: func});
}
function post_clone_test(srcdoc, testfunc)
{
posted_items.push({srcdoc, testfunc});
}
function handle_posted_items()
{
if (posted_items.length == 0) {
SimpleTest.finish();
return;
}
if ("state" in posted_items[0]) { var item = posted_items.shift();
item.state();
handle_posted_items();
return;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.