1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/style/test/test_rule_insertion.html Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,214 @@ 1.4 +<!DOCTYPE HTML> 1.5 +<html> 1.6 +<!-- 1.7 +https://bugzilla.mozilla.org/show_bug.cgi?id=816720 1.8 +--> 1.9 +<head> 1.10 + <title>Test for Bug 816720</title> 1.11 + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> 1.12 + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> 1.13 + <style type="text/css" id="style"></style> 1.14 +</head> 1.15 +<body> 1.16 + 1.17 +<pre id="test"></pre> 1.18 + 1.19 +<p><span id=control-serif>........</span></p> 1.20 +<p><span id=control-monospace>........</span></p> 1.21 +<p><span id=test-font>........</span></p> 1.22 + 1.23 +<style id=other-styles> 1.24 + #test { font-size: 16px; animation: test 1s both } 1.25 + #control-serif { font: 16px serif } 1.26 + #test-font { font: 16px UnlikelyFontName, serif } 1.27 +</style> 1.28 + 1.29 +<script type="application/javascript"> 1.30 + 1.31 +// Monospace fonts available on all the platforms we're testing on. 1.32 +// 1.33 +// XXX Once bug 817220 is fixed we could instead use the value of 1.34 +// font.name.monospace.x-western as the monospace font to use. 1.35 +var MONOSPACE_FONTS = [ 1.36 + "Courier", 1.37 + "Courier New", 1.38 + "Monaco", 1.39 + "DejaVu Sans Mono", 1.40 + "Droid Sans Mono" 1.41 +]; 1.42 + 1.43 +var test = document.getElementById("test"); 1.44 +var controlSerif = document.getElementById("control-serif"); 1.45 +var controlMonospace = document.getElementById("control-monospace"); 1.46 +var testFont = document.getElementById("test-font"); 1.47 +var otherStyles = document.getElementById("other-styles"); 1.48 + 1.49 +otherStyles.sheet.insertRule("#control-monospace { font: 16px " + 1.50 + MONOSPACE_FONTS + ", serif }", 0); 1.51 + 1.52 +var monospaceWidth = controlMonospace.getBoundingClientRect().width; 1.53 +var serifWidth = controlSerif.getBoundingClientRect().width; 1.54 + 1.55 +// [at-rule type, passing condition, failing condition] 1.56 +var outerRuleInfo = [ 1.57 + ["@media", "all", "not all"], 1.58 + ["@-moz-document", "url-prefix('')", "url-prefix('zzz')"], 1.59 + ["@supports", "(color: green)", "(unknown: unknown)"] 1.60 +]; 1.61 + 1.62 +// [rule, function to test whether the rule was successfully inserted and applied] 1.63 +var innerRuleInfo = [ 1.64 + ["#test { text-decoration: underline; }", 1.65 + function(aApplied, aParent, aException) { 1.66 + return !aException && 1.67 + window.getComputedStyle(test, "").textDecoration == 1.68 + (aApplied ? "underline" : "none"); 1.69 + }], 1.70 + ["@page { margin: 4cm; }", 1.71 + function(aApplied, aParent, aException) { 1.72 + // just test whether it threw 1.73 + return !aException; 1.74 + }], 1.75 + ["@keyframes test { from { font-size: 100px; } to { font-size: 100px; } }", 1.76 + function(aApplied, aParent, aException) { 1.77 + return !aException && 1.78 + window.getComputedStyle(test, "").fontSize == 1.79 + (aApplied ? "100px" : "16px") 1.80 + }], 1.81 + ["@font-face { font-family: UnlikelyFontName; src: " + 1.82 + MONOSPACE_FONTS.map(function(s) { return "local('" + s + "')" }).join(", ") + "; }", 1.83 + function(aApplied, aParent, aException) { 1.84 + var width = testFont.getBoundingClientRect().width; 1.85 + if (aException) { 1.86 + return false; 1.87 + } 1.88 + if (navigator.oscpu.match(/Linux/) || 1.89 + navigator.oscpu.match(/Android/) || 1.90 + SpecialPowers.Services.appinfo.name == "B2G") { 1.91 + return true; 1.92 + } 1.93 + return Math.abs(width - (aApplied ? monospaceWidth : serifWidth)) <= 1; // bug 769194 prevents local() 1.94 + // fonts working on Android 1.95 + }], 1.96 + ["@charset 'UTF-8';", 1.97 + function(aApplied, aParent, aException) { 1.98 + // just test whether it threw 1.99 + return aParent instanceof CSSRule ? aException : !aException; 1.100 + }], 1.101 + ["@import url(nothing.css);", 1.102 + function(aApplied, aParent, aException) { 1.103 + // just test whether it threw 1.104 + return aParent instanceof CSSRule ? aException : !aException; 1.105 + }], 1.106 + ["@namespace test url(http://example.org);", 1.107 + function(aApplied, aParent, aException) { 1.108 + // just test whether it threw 1.109 + return aParent instanceof CSSRule ? aException : !aException; 1.110 + }], 1.111 +]; 1.112 + 1.113 +function runTest() 1.114 +{ 1.115 + // First, assert that our assumed available fonts are indeed available 1.116 + // and have expected metrics. 1.117 + ok(monospaceWidth > 0, "monospace text has width"); 1.118 + ok(serifWidth > 0, "serif text has width"); 1.119 + ok(Math.abs(monospaceWidth - serifWidth) > 1, "monospace and serif text have sufficiently different widths"); 1.120 + 1.121 + // And that the #test-font element starts off using the "serif" font. 1.122 + var initialFontTestWidth = testFont.getBoundingClientRect().width; 1.123 + is(initialFontTestWidth, serifWidth); 1.124 + 1.125 + // We construct a style sheet with zero, one or two levels of conditional 1.126 + // grouping rules (taken from outerRuleInfo), with one of the inner rules 1.127 + // at the deepest level. 1.128 + var style = document.getElementById("style"); 1.129 + 1.130 + // For each of the outer rule types... 1.131 + for (var outerRule1 = 0; outerRule1 < outerRuleInfo.length; outerRule1++) { 1.132 + // For each of { 0 = don't create an outer rule, 1.133 + // 1 = create an outer rule with a passing condition, 1.134 + // 2 = create an outer rule with a failing condition }... 1.135 + for (var outerRuleCondition1 = 0; outerRuleCondition1 <= 2; outerRuleCondition1++) { 1.136 + 1.137 + // For each of the outer rule types again... 1.138 + for (var outerRule2 = 0; outerRule2 < outerRuleInfo.length; outerRule2++) { 1.139 + // For each of { 0 = don't create an outer rule, 1.140 + // 1 = create an outer rule with a passing condition, 1.141 + // 2 = create an outer rule with a failing condition } again... 1.142 + for (var outerRuleCondition2 = 0; outerRuleCondition2 <= 2; outerRuleCondition2++) { 1.143 + 1.144 + // For each of the inner rule types... 1.145 + for (var innerRule = 0; innerRule < innerRuleInfo.length; innerRule++) { 1.146 + 1.147 + // Clear rules 1.148 + var object = style.sheet; 1.149 + while (object.cssRules.length) { 1.150 + object.deleteRule(0); 1.151 + } 1.152 + 1.153 + // We'll record whether the inner rule should have been applied, 1.154 + // according to whether we put passing or failing conditional 1.155 + // grouping rules around it. 1.156 + var applied = true; 1.157 + 1.158 + if (outerRuleCondition1) { 1.159 + // Create an outer conditional rule. 1.160 + object.insertRule([outerRuleInfo[outerRule1][0], 1.161 + outerRuleInfo[outerRule1][outerRuleCondition1], 1.162 + "{}"].join(" "), 0); 1.163 + object = object.cssRules[0]; 1.164 + 1.165 + if (outerRuleCondition1 == 2) { 1.166 + // If we used a failing condition, we don't expect the inner 1.167 + // rule to be applied. 1.168 + applied = false; 1.169 + } 1.170 + } 1.171 + 1.172 + if (outerRuleCondition2) { 1.173 + // Create another outer conditional rule as a child of the first 1.174 + // outer conditional rule (or the style sheet, if we didn't create 1.175 + // a first outer conditional rule). 1.176 + object.insertRule([outerRuleInfo[outerRule2][0], 1.177 + outerRuleInfo[outerRule2][outerRuleCondition2], 1.178 + "{}"].join(" "), 0); 1.179 + object = object.cssRules[0]; 1.180 + 1.181 + if (outerRuleCondition2 == 2) { 1.182 + // If we used a failing condition, we don't expect the inner 1.183 + // rule to be applied. 1.184 + applied = false; 1.185 + } 1.186 + } 1.187 + 1.188 + var outer = object instanceof CSSRule ? object.cssText : "style sheet"; 1.189 + var inner = innerRuleInfo[innerRule][0]; 1.190 + 1.191 + // Insert the inner rule. 1.192 + var exception = null; 1.193 + try { 1.194 + object.insertRule(inner, 0); 1.195 + } catch (e) { 1.196 + exception = e; 1.197 + } 1.198 + 1.199 + ok(innerRuleInfo[innerRule][1](applied, object, exception), 1.200 + "<" + [outerRule1, outerRuleCondition1, outerRule2, 1.201 + outerRuleCondition2, innerRule].join(",") + "> " + 1.202 + "inserting " + inner + " into " + outer.replace(/ *\n */g, ' ')); 1.203 + } 1.204 + } 1.205 + } 1.206 + } 1.207 + } 1.208 + 1.209 + SimpleTest.finish(); 1.210 +} 1.211 + 1.212 +SimpleTest.waitForExplicitFinish(); 1.213 +SpecialPowers.pushPrefEnv({ "set": [["layout.css.supports-rule.enabled", true]] }, runTest); 1.214 + 1.215 +</script> 1.216 +</body> 1.217 +</html>