layout/style/test/test_font_feature_values_parsing.html

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/layout/style/test/test_font_feature_values_parsing.html	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,360 @@
     1.4 +<!DOCTYPE HTML>
     1.5 +<html>
     1.6 +<head>
     1.7 +  <meta charset=utf-8>
     1.8 +  <title>@font-feature-values rule parsing tests</title>
     1.9 +  <link rel="author" title="John Daggett" href="mailto:jdaggett@mozilla.com">
    1.10 +  <link rel="help" href="http://www.w3.org/TR/css3-fonts/#font-feature-values" />
    1.11 +  <meta name="assert" content="tests that valid @font-feature-values rules parse and invalid ones don't" />
    1.12 +  <!-- https://bugzilla.mozilla.org/show_bug.cgi?id=549861 -->
    1.13 +  <script type="text/javascript" src="/resources/testharness.js"></script>
    1.14 +  <script type="text/javascript" src="/resources/testharnessreport.js"></script>
    1.15 +  <style type="text/css">
    1.16 +  </style>
    1.17 +</head>
    1.18 +<body>
    1.19 +<div id="log"></div>
    1.20 +<pre id="display"></pre>
    1.21 +<style type="text/css" id="testbox"></style>
    1.22 +
    1.23 +<script type="text/javascript">
    1.24 +var gPrefix = "";
    1.25 +var kFontFeatureValuesRuleType = 14;
    1.26 +
    1.27 +function ruleName() { return "@" + gPrefix + "font-feature-values"; }
    1.28 +function makeRule(f, v) {
    1.29 +  return ruleName() + " " + f + " { " + v + " }";
    1.30 +}
    1.31 +
    1.32 +function _()
    1.33 +{
    1.34 +  var i, decl = [];
    1.35 +  for (i = 0; i < arguments.length; i++) {
    1.36 +    decl.push(arguments[i]);
    1.37 +  }
    1.38 +  return makeRule("bongo", decl.join(" "));
    1.39 +}
    1.40 +
    1.41 +// note: because of bugs in the way family names are serialized,
    1.42 +// 'serializationSame' only implies that the value definition block
    1.43 +// is the same (i.e. not including the family name list)
    1.44 +
    1.45 +var testrules = [
    1.46 +
    1.47 +  /* basic syntax */
    1.48 +  { rule: ruleName() + ";", invalid: true },
    1.49 +  { rule: ruleName() + " bongo;", invalid: true },
    1.50 +  { rule: ruleName().replace("values", "value") + " {;}", invalid: true },
    1.51 +  { rule: ruleName().replace("feature", "features") + " {;}", invalid: true },
    1.52 +  { rule: makeRule("bongo", ""), serializationNoValueDefn: true },
    1.53 +  { rule: makeRule("bongo", ";"), serializationNoValueDefn: true },
    1.54 +  { rule: makeRule("bongo", ",;"), serializationNoValueDefn: true },
    1.55 +  { rule: makeRule("bongo", ";,"), serializationNoValueDefn: true },
    1.56 +  { rule: makeRule("bongo", ",;,"), serializationNoValueDefn: true },
    1.57 +  { rule: makeRule("bongo", "@styleset;"), serializationNoValueDefn: true },
    1.58 +  { rule: makeRule("bongo", "@styleset,;"), serializationNoValueDefn: true },
    1.59 +  { rule: makeRule("bongo", "@styleset abc;"), serializationNoValueDefn: true },
    1.60 +  { rule: makeRule("bongo", "@styleset { abc }"), serializationNoValueDefn: true },
    1.61 +  { rule: makeRule("bongo", "@styleset { ;;abc }"), serializationNoValueDefn: true },
    1.62 +  { rule: makeRule("bongo", "@styleset { abc;; }"), serializationNoValueDefn: true },
    1.63 +  { rule: makeRule("bongo", "@styleset { abc: }"), serializationNoValueDefn: true },
    1.64 +  { rule: makeRule("bongo", "@styleset { abc,: }"), serializationNoValueDefn: true },
    1.65 +  { rule: makeRule("bongo", "@styleset { abc:, }"), serializationNoValueDefn: true },
    1.66 +  { rule: makeRule("bongo", "@styleset { abc:,; }"), serializationNoValueDefn: true },
    1.67 +  { rule: makeRule("bongo", "@styleset { a,b }"), serializationNoValueDefn: true },
    1.68 +  { rule: makeRule("bongo", "@styleset { a;b }"), serializationNoValueDefn: true },
    1.69 +  { rule: makeRule("bongo", "@styleset { a:;b: }"), serializationNoValueDefn: true },
    1.70 +  { rule: makeRule("bongo", "@styleset { a:,;b: }"), serializationNoValueDefn: true },
    1.71 +  { rule: makeRule("bongo", "@styleset { a:1,;b: }"), serializationNoValueDefn: true },
    1.72 +  { rule: makeRule("bongo", "@styleset { abc 1 2 3 }"), serializationNoValueDefn: true },
    1.73 +  { rule: makeRule("bongo", "@styleset { abc:, 1 2 3 }"), serializationNoValueDefn: true },
    1.74 +  { rule: makeRule("bongo", "@styleset { abc:; 1 2 3 }"), serializationNoValueDefn: true },
    1.75 +  { rule: makeRule("bongo", "@styleset { abc:; 1 2 3 }"), serializationNoValueDefn: true },
    1.76 +  { rule: makeRule("bongo", "@styleset { abc: 1 2 3a }"), serializationNoValueDefn: true },
    1.77 +  { rule: makeRule("bongo", "@styleset { abc: 1 2 3, def: 1; }"), serializationNoValueDefn: true },
    1.78 +  { rule: makeRule("bongo", "@blah @styleset { abc: 1 2 3; }"), serializationNoValueDefn: true },
    1.79 +  { rule: makeRule("bongo", "@blah } @styleset { abc: 1 2 3; }"), serializationNoValueDefn: true },
    1.80 +  { rule: makeRule("bongo", "@blah , @styleset { abc: 1 2 3; }"), serializationNoValueDefn: true },
    1.81 +  { rule: ruleName() + " bongo { @styleset { abc: 1 2 3; }", serialization: _("@styleset { abc: 1 2 3; }") },
    1.82 +  { rule: ruleName() + " bongo { @styleset { abc: 1 2 3 }", serialization: _("@styleset { abc: 1 2 3; }") },
    1.83 +  { rule: ruleName() + " bongo { @styleset { abc: 1 2 3;", serialization: _("@styleset { abc: 1 2 3; }") },
    1.84 +  { rule: ruleName() + " bongo { @styleset { abc: 1 2 3", serialization: _("@styleset { abc: 1 2 3; }") },
    1.85 +  { rule: _("@styleset { ok-1: 1; }"), serializationSame: true },
    1.86 +  { rule: _("@annotation { ok-1: 3; }"), serializationSame: true },
    1.87 +  { rule: _("@stylistic { blah: 3; }"), serializationSame: true },
    1.88 +  { rule: makeRule("bongo", "\n@styleset\n  { blah: 3; super-blah: 4 5;\n  more-blah: 5 6 7;\n }"), serializationSame: true },
    1.89 +  { rule: makeRule("bongo", "\n@styleset\n  {\n blah:\n 3\n;\n super-blah:\n 4\n 5\n;\n  more-blah:\n 5 6\n 7;\n }"), serializationSame: true },
    1.90 +
    1.91 +  /* limits on number of values */
    1.92 +  { rule: _("@stylistic { blah: 1; }"), serializationSame: true },
    1.93 +  { rule: _("@styleset { blah: 1 2 3 4; }"), serializationSame: true },
    1.94 +  { rule: _("@character-variant { blah: 1 2; }"), serializationSame: true },
    1.95 +  { rule: _("@swash { blah: 1; }"), serializationSame: true },
    1.96 +  { rule: _("@ornaments { blah: 1; }"), serializationSame: true },
    1.97 +  { rule: _("@annotation { blah: 1; }"), serializationSame: true },
    1.98 +
    1.99 +  /* values ignored when used */
   1.100 +  { rule: _("@styleset { blah: 0; }"), serializationSame: true },
   1.101 +  { rule: _("@styleset { blah: 120 124; }"), serializationSame: true },
   1.102 +  { rule: _("@character-variant { blah: 0; }"), serializationSame: true },
   1.103 +  { rule: _("@character-variant { blah: 111; }"), serializationSame: true },
   1.104 +  { rule: _("@character-variant { blah: 111 13; }"), serializationSame: true },
   1.105 +
   1.106 +  /* invalid value name */
   1.107 +  { rulesrc: ["styleset { blah: 1 }"], serializationNoValueDefn: true },
   1.108 +  { rulesrc: ["stylistic { blah: 1 }"], serializationNoValueDefn: true },
   1.109 +  { rulesrc: ["character-variant { blah: 1 }"], serializationNoValueDefn: true },
   1.110 +  { rulesrc: ["swash { blah: 1 }"], serializationNoValueDefn: true },
   1.111 +  { rulesrc: ["ornaments { blah: 1 }"], serializationNoValueDefn: true },
   1.112 +  { rulesrc: ["annotation { blah: 1 }"], serializationNoValueDefn: true },
   1.113 +  { rulesrc: ["@bongo { blah: 1 }"], serializationNoValueDefn: true },
   1.114 +  { rulesrc: ["@bongo { blah: 1 2 3 }"], serializationNoValueDefn: true },
   1.115 +  { rulesrc: ["@bongo { blah: 1 2 3; burp: 1;;; }"], serializationNoValueDefn: true },
   1.116 +
   1.117 +  /* values */
   1.118 +  { rulesrc: ["@styleset { blah: -1 }"], serializationNoValueDefn: true },
   1.119 +  { rulesrc: ["@styleset { blah: 1 -1 }"], serializationNoValueDefn: true },
   1.120 +  { rulesrc: ["@styleset { blah: 1.5 }"], serializationNoValueDefn: true },
   1.121 +  { rulesrc: ["@styleset { blah: 15px }"], serializationNoValueDefn: true },
   1.122 +  { rulesrc: ["@styleset { blah: red }"], serializationNoValueDefn: true },
   1.123 +  { rulesrc: ["@styleset { blah: (1) }"], serializationNoValueDefn: true },
   1.124 +  { rulesrc: ["@styleset { blah:(1) }"], serializationNoValueDefn: true },
   1.125 +  { rulesrc: ["@styleset { blah:, 1 }"], serializationNoValueDefn: true },
   1.126 +  { rulesrc: ["@styleset { blah: <1> }"], serializationNoValueDefn: true },
   1.127 +  { rulesrc: ["@styleset { blah: 1! }"], serializationNoValueDefn: true },
   1.128 +  { rulesrc: ["@styleset { blah: 1,, }"], serializationNoValueDefn: true },
   1.129 +  { rulesrc: ["@styleset { blah: 1 1 1 1; }"], serializationSame: true },
   1.130 +
   1.131 +  /* limits on number of values */
   1.132 +  { rulesrc: ["@stylistic { blah: 1 2 }"], serializationNoValueDefn: true },
   1.133 +  { rulesrc: ["@character-variant { blah: 1 2 3 }"], serializationNoValueDefn: true },
   1.134 +  { rulesrc: ["@swash { blah: 1 2 }"], serializationNoValueDefn: true },
   1.135 +  { rulesrc: ["@ornaments { blah: 1 2 }"], serializationNoValueDefn: true },
   1.136 +  { rulesrc: ["@annotation { blah: 1 2 }"], serializationNoValueDefn: true },
   1.137 +  { rulesrc: ["@styleset { blah: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19; }"], serializationSame: true },
   1.138 +
   1.139 +  /* family names */
   1.140 +  { rule: makeRule("bongo", "@styleset { blah: 1; }"), serializationSame: true },
   1.141 +  { rule: makeRule("\"bongo\"", "@styleset { blah: 1; }"), serializationSame: true },
   1.142 +  { rule: makeRule("'bongo'", "@styleset { blah: 1; }"), serializationSame: true },
   1.143 +  { rule: makeRule("\\62 ongo", "@styleset { blah: 1; }"), serializationSame: true },
   1.144 +  { rule: makeRule("bongo, super bongo, bongo the supreme", "@styleset { blah: 1; }"), serializationSame: true },
   1.145 +  { rule: makeRule("bongo,, super bongo", "@styleset { blah: 1; }"), invalid: true },
   1.146 +  { rule: makeRule("bongo,*", "@styleset { blah: 1; }"), invalid: true },
   1.147 +  { rule: makeRule("bongo, sans-serif", "@styleset { blah: 1; }"), invalid: true },
   1.148 +  { rule: makeRule("serif, sans-serif", "@styleset { blah: 1; }"), invalid: true },
   1.149 +  { rule: makeRule("'serif', 'sans-serif'", "@styleset { blah: 1; }"), serializationSame: true },
   1.150 +  { rule: makeRule("bongo, \"super bongo\", 'bongo the supreme'", "@styleset { blah: 1; }"), serializationSame: true },
   1.151 +  { rule: makeRule("毎日カレーを食べたい!", "@styleset { blah: 1; }"), serializationSame: true },
   1.152 +  { rule: makeRule("毎日カレーを食べたい!, 納豆嫌い", "@styleset { blah: 1; }"), serializationSame: true },
   1.153 +
   1.154 +  { rule: makeRule("bongo, \"super\" bongo, bongo the supreme", "@styleset { blah: 1; }"), invalid: true },
   1.155 +  { rule: makeRule("--bongo", "@styleset { blah: 1; }"), invalid: true },
   1.156 +
   1.157 +  /* ident tests */
   1.158 +  { rule: _("@styleset { blah: 1; blah: 1; }"), serializationSame: true },
   1.159 +  { rule: _("@styleset { blah: 1; de-blah: 1; blah: 2; }"), serializationSame: true },
   1.160 +  { rule: _("@styleset { \\tra-la: 1; }"), serialization: _("@styleset { tra-la: 1; }") },
   1.161 +  { rule: _("@styleset { b\\lah: 1; }"), serialization: _("@styleset { blah: 1; }") },
   1.162 +  { rule: _("@styleset { \\62 lah: 1; }"), serialization: _("@styleset { blah: 1; }") },
   1.163 +  { rule: _("@styleset { \\:blah: 1; }"), serialization: _("@styleset { \\:blah: 1; }") },
   1.164 +  { rule: _("@styleset { \\;blah: 1; }"), serialization: _("@styleset { \\;blah: 1; }") },
   1.165 +  { rule: _("@styleset { complex\\20 blah: 1; }"), serialization: _("@styleset { complex\\ blah: 1; }") },
   1.166 +  { rule: _("@styleset { complex\\ blah: 1; }"), serializationSame: true },
   1.167 +  { rule: _("@styleset { Håkon: 1; }"), serializationSame: true },
   1.168 +  { rule: _("@styleset { Åквариум: 1; }"), serializationSame: true },
   1.169 +  { rule: _("@styleset { \\1f449\\1f4a9\\1f448: 1; }"), serialization: _("@styleset { 👉💩👈: 1; }") },
   1.170 +  { rule: _("@styleset { 魅力: 1; }"), serializationSame: true },
   1.171 +  { rule: _("@styleset { 毎日カレーを食べたい!: 1; }"), serializationSame: true },
   1.172 +  /* from http://en.wikipedia.org/wiki/Metal_umlaut */
   1.173 +  { rule: _("@styleset { TECHNICIÄNS\\ ÖF\\ SPÅCE\\ SHIP\\ EÅRTH\\ THIS\\ IS\\ YÖÜR\\ CÄPTÅIN\\ SPEÄKING\\ YÖÜR\\ ØÅPTÅIN\\ IS\\ DEA̋D: 1; }"), serializationSame: true },
   1.174 +
   1.175 +  { rulesrc: ["@styleset { 123blah: 1; }"], serializationNoValueDefn: true },
   1.176 +  { rulesrc: ["@styleset { :123blah 1; }"], serializationNoValueDefn: true },
   1.177 +  { rulesrc: ["@styleset { :123blah: 1; }"], serializationNoValueDefn: true },
   1.178 +  { rulesrc: ["@styleset { ?123blah: 1; }"], serializationNoValueDefn: true },
   1.179 +  { rulesrc: ["@styleset { \"blah\": 1; }"], serializationNoValueDefn: true },
   1.180 +  { rulesrc: ["@styleset { complex blah: 1; }"], serializationNoValueDefn: true },
   1.181 +  { rulesrc: ["@styleset { complex\\  blah: 1; }"], serializationNoValueDefn: true }
   1.182 +
   1.183 +];
   1.184 +
   1.185 +// test that invalid value declarations don't affect the parsing of surrounding 
   1.186 +// declarations.  So before + invalid + after should match the serialization 
   1.187 +// given in s.
   1.188 +
   1.189 +var gSurroundingTests = [
   1.190 +  // -- invalid, valid ==> valid
   1.191 +  { before: "", after: "@ornaments { whatchamacallit-1: 23; thingy-dingy: 3; }", s: _("@ornaments { whatchamacallit-1: 23; thingy-dingy: 3; }") },
   1.192 +
   1.193 +  // -- valid, invalid ==> valid
   1.194 +  { before: "@ornaments { whatchamacallit-1: 23; thingy-dingy: 7; }", after: "", s: _("@ornaments { whatchamacallit-1: 23; thingy-dingy: 7; }") },
   1.195 +
   1.196 +  // -- valid, invalid, valid ==> valid, valid
   1.197 +  { before: "@ornaments { whatchamacallit-1: 23; thingy-dingy: 3; }", after: "@character-variant { whatchamacallit-2: 23 4; }", s: _("@ornaments { whatchamacallit-1: 23; thingy-dingy: 3; } @character-variant { whatchamacallit-2: 23 4; }") },
   1.198 +
   1.199 +  // -- invalid, valid, invalid ==> valid
   1.200 +  { between: "@ornaments { whatchamacallit-1: 23; thingy-dingy: 4; }", s: _("@ornaments { whatchamacallit-1: 23; thingy-dingy: 4; }") }
   1.201 +];
   1.202 +
   1.203 +/* strip out just values, along with empty value blocks (e.g. @swash { })*/
   1.204 +function valuesText(ruletext)
   1.205 +{
   1.206 +  var t = ruletext.replace(/@[a-zA-Z0-9\-]+[ \n]*{[ \n]*}/g, "");
   1.207 +  t = t.replace(/[ \n]+/g, " ");
   1.208 +  t = t.replace(/^[^{]+{[ \n]*/, "");
   1.209 +  t = t.replace(/[ \n]*}[^}]*$/, "");
   1.210 +  t = t.replace(/[ \n]*;/g, ";");
   1.211 +  return t;
   1.212 +}
   1.213 +
   1.214 +function testParse(rulesrc)
   1.215 +{
   1.216 +  var sheet = document.styleSheets[1];
   1.217 +  var rule = _.apply(this, rulesrc);
   1.218 +
   1.219 +  while(sheet.cssRules.length > 0)
   1.220 +    sheet.deleteRule(0);
   1.221 +  try {
   1.222 +    sheet.insertRule(rule, 0);
   1.223 +  } catch (e) {
   1.224 +    return e.toString();
   1.225 +  }
   1.226 +
   1.227 +  if (sheet.cssRules.length == 1 && sheet.cssRules[0].type == kFontFeatureValuesRuleType) {
   1.228 +    return sheet.cssRules[0].cssText.replace(/[ \n]+/g, " ");
   1.229 +  }
   1.230 +
   1.231 +  return "";
   1.232 +}
   1.233 +
   1.234 +function testOneRule(testrule) {
   1.235 +  var sheet = document.styleSheets[1];
   1.236 +  var rule;
   1.237 +
   1.238 +  if ("rulesrc" in testrule) {
   1.239 +    rule = _.apply(this, testrule.rulesrc);
   1.240 +  } else {
   1.241 +    rule = testrule.rule;
   1.242 +  }
   1.243 +
   1.244 +  var parseErr = false;
   1.245 +  var expectedErr = false;
   1.246 +  var invalid = false;
   1.247 +  if ("invalid" in testrule && testrule.invalid) invalid = true;
   1.248 +
   1.249 +  while(sheet.cssRules.length > 0)
   1.250 +    sheet.deleteRule(0);
   1.251 +  try {
   1.252 +    sheet.insertRule(rule, 0);
   1.253 +  } catch (e) {
   1.254 +    expectedErr = (e.name == "SyntaxError"
   1.255 +      && e instanceof DOMException
   1.256 +      && e.code == DOMException.SYNTAX_ERR
   1.257 +      && invalid);
   1.258 +    parseErr = true;
   1.259 +  }
   1.260 +
   1.261 +  test(function() { 
   1.262 +    assert_true(!parseErr || expectedErr, "unexpected syntax error");
   1.263 +    if (!parseErr) {
   1.264 +      assert_equals(sheet.cssRules.length, 1, "bad rule count");
   1.265 +      assert_equals(sheet.cssRules[0].type, kFontFeatureValuesRuleType, "bad rule type");
   1.266 +    }
   1.267 +  }, "basic parse tests - " + rule);
   1.268 +
   1.269 +  var sanitizedRule = rule.replace(/[ \n]+/g, " ");
   1.270 +  if (parseErr) {
   1.271 +    return;
   1.272 +  }
   1.273 +
   1.274 +  // should result in one @font-feature-values rule constructed
   1.275 +
   1.276 +  // serialization matches expectation
   1.277 +  // -- note: due to inconsistent font family serialization problems,
   1.278 +  //    only the serialization of the values is tested currently
   1.279 +
   1.280 +  var ruleValues = valuesText(rule);
   1.281 +  var serialized = sheet.cssRules[0].cssText;
   1.282 +  var serializedValues = valuesText(serialized);
   1.283 +  var haveSerialization = true;
   1.284 +
   1.285 +  if (testrule.serializationSame) {
   1.286 +    test(function() {
   1.287 +      assert_equals(serializedValues, ruleValues, "canonical cssText serialization doesn't match");
   1.288 +    }, "serialization check - " + rule);
   1.289 +  } else if ("serialization" in testrule) {
   1.290 +    var s = valuesText(testrule.serialization);
   1.291 +    test(function() {
   1.292 +      assert_equals(serializedValues, s, "non-canonical cssText serialization doesn't match - ");
   1.293 +    }, "serialization check - " + rule);
   1.294 +  } else if (testrule.serializationNoValueDefn) {
   1.295 +    test(function() {
   1.296 +      assert_equals(serializedValues, "", "cssText serialization should have no value defintions - ");
   1.297 +    }, "no value definitions in serialization - " + rule);
   1.298 +
   1.299 +    haveSerialization = false;
   1.300 +
   1.301 +    if ("rulesrc" in testrule) {
   1.302 +      test(function() {
   1.303 +        var j, rulesrc = testrule.rulesrc;
   1.304 +    
   1.305 +        // invalid value definitions shouldn't affect the parsing of valid
   1.306 +        // definitions before or after an invalid one
   1.307 +        for (var j = 0; j < gSurroundingTests.length; j++) {
   1.308 +          var t = gSurroundingTests[j];
   1.309 +          var srulesrc = [];
   1.310 +    
   1.311 +          if ("between" in t) {
   1.312 +            srulesrc = srulesrc.concat(rulesrc);
   1.313 +            srulesrc = srulesrc.concat(t.between);
   1.314 +            srulesrc = srulesrc.concat(rulesrc);
   1.315 +          } else {
   1.316 +            if (t.before != "")
   1.317 +              srulesrc = srulesrc.concat(t.before);
   1.318 +            srulesrc = srulesrc.concat(rulesrc);
   1.319 +            if (t.after != "")
   1.320 +              srulesrc = srulesrc.concat(t.after);
   1.321 +          }
   1.322 +    
   1.323 +          var result = testParse(srulesrc);
   1.324 +          assert_equals(valuesText(result), valuesText(t.s), "invalid declarations should not affect valid ones - ");
   1.325 +        }
   1.326 +      }, "invalid declarations don't affect valid ones - " + rule);
   1.327 +    }
   1.328 +  }
   1.329 +
   1.330 +  // if serialization non-empty, serialization should round-trip to itself
   1.331 +  if (haveSerialization) {
   1.332 +    var roundTripText = testParse([serializedValues]);
   1.333 +    test(function() {
   1.334 +      assert_equals(valuesText(roundTripText), serializedValues,
   1.335 +         "serialization should round-trip to itself - ");
   1.336 +    }, "serialization round-trip - " + rule);
   1.337 +  }
   1.338 +}
   1.339 +
   1.340 +function testFontFeatureValuesRuleParsing() {
   1.341 +  // Gecko-specific check - if pref not set, skip these tests
   1.342 +  if (window.SpecialPowers && !window.SpecialPowers.getBoolPref("layout.css.font-features.enabled")) {
   1.343 +    return;
   1.344 +  }
   1.345 +  var i;
   1.346 +  for (i = 0; i < testrules.length; i++) {
   1.347 +    var testrule = testrules[i];
   1.348 +    var rule;
   1.349 +
   1.350 +    if ("rulesrc" in testrule) {
   1.351 +      rule = _.apply(this, testrule.rulesrc);
   1.352 +    } else {
   1.353 +      rule = testrule.rule;
   1.354 +    }
   1.355 +
   1.356 +    testOneRule(testrule);
   1.357 +    //test(function() { testOneRule(testrule); }, "parsing " + rule);
   1.358 +  }
   1.359 +}
   1.360 +
   1.361 +testFontFeatureValuesRuleParsing();
   1.362 +</script>
   1.363 +</body></html>

mercurial