summaryrefslogtreecommitdiffstats
path: root/layout/style/test/test_garbage_at_end_of_declarations.html
blob: 5be02a295b8b28b67cddad026997756ecb582657 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
<!DOCTYPE HTML>
<html>
<!--
-->
<head>
  <title>Test handling of garbage at the end of CSS declarations</title>
  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
  <script type="text/javascript" src="property_database.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none">

<div id="testnode"></div>
  
</div>
<pre id="test">
<script class="testbody" type="text/javascript">

/** Test for correct ExpectEndProperty calls in CSS parser **/

/*
 * Inspired by review comments on bug 378217.
 *
 * The original idea was to test that ExpectEndProperty calls are made
 * in the correct places in the CSS parser so that we don't accept
 * garbage at the end of property values.
 *
 * However, there's actually other code (in ParseDeclaration) that
 * ensures that we don't accept garbage.
 *
 * Despite that, I'm checking it in anyway, since it caught an infinite
 * loop in the patch for bug 435441.
 */

var gElement = document.getElementById("testnode");
var gDeclaration = gElement.style;
var gUnsetValueEnabled = SpecialPowers.getBoolPref("layout.css.unset-value.enabled");

/*
 * This lists properties where garbage identifiers are allowed at the
 * end, with values in property_database.js that are exceptions that
 * should be tested anyway.  "inherit", "initial" and "unset" are always
 * tested.
 */
var gAllowsExtra = {
  "counter-increment": { "none": true },
  "counter-reset": { "none": true },
  "font-family": {},
  "font": { "caption": true, "icon": true, "menu": true, "message-box": true,
            "small-caption": true, "status-bar": true },
  "voice-family": {},
  "list-style": {
    "inside none": true, "none inside": true, "none": true,
    "none outside": true, "outside none": true,
    'url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==")': true,
    'url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==") outside': true,
    'outside url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKElEQVR42u3NQQ0AAAgEoNP+nTWFDzcoQE1udQQCgUAgEAgEAsGTYAGjxAE/G/Q2tQAAAABJRU5ErkJggg==")': true
  },
};

/* These are the reverse of the above list; they're the unusual values
   that do allow extra keywords afterwards */
var gAllowsExtraUnusual = {
  "transition": { "all": true, "0s": true, "0s 0s": true, "ease": true,
                  "1s 2s linear": true, "1s linear 2s": true,
                  "linear 1s 2s": true, "linear 1s": true,
                  "1s linear": true, "1s 2s": true, "2s 1s": true,
                  "linear": true, "1s": true, "2s": true,
                  "ease-in-out": true, "2s ease-in": true,
                  "ease-out 2s": true, "1s width, 2s": true },
  "animation": { "none": true, "0s": true, "ease": true,
                 "normal": true, "running": true, "1.0": true,
                 "1s 2s linear": true, "1s linear 2s": true,
                 "linear 1s 2s": true, "linear 1s": true,
                 "1s linear": true, "1s 2s": true, "2s 1s": true,
                 "linear": true, "1s": true, "2s": true,
                 "ease-in-out": true, "2s ease-in": true,
                 "ease-out 2s": true, "1s bounce, 2s": true,
                 "1s bounce, 2s none": true },
  "font-family": { "inherit": true, "initial": true, "unset": true }
};

gAllowsExtraUnusual["-moz-transition"] = gAllowsExtraUnusual["transition"];
gAllowsExtraUnusual["-moz-animation"] = gAllowsExtraUnusual["animation"];

function test_property(property)
{
  var info = gCSSProperties[property];

  function test_value(value) {
    if (property in gAllowsExtra &&
        value != "inherit" && value != "initial" && value != "unset" &&
        !(value in gAllowsExtra[property])) {
      return;
    }
    if (property in gAllowsExtraUnusual &&
        value in gAllowsExtraUnusual[property]) {
      return;
    }

    // Include non-identifier characters in the garbage
    // in case |value| would also be valid with a <custom-ident> added.
    gElement.setAttribute("style", property + ": " + value + " +blah/");
    if ("subproperties" in info) {
      for (idx in info.subproperties) {
        var subprop = info.subproperties[idx];
        is(gDeclaration.getPropertyValue(subprop), "",
           ["expected garbage ignored after '", property, ": ", value,
            "' when looking at subproperty '", subprop, "'"].join(""));
      }
    } else {
      is(gDeclaration.getPropertyValue(property), "",
         ["expected garbage ignored after '", property, ": ", value,
          "'"].join(""));
    }
  }

  var idx;
  test_value("inherit");
  test_value("initial");
  if (gUnsetValueEnabled)
    test_value("unset");
  for (idx in info.initial_values)
    test_value(info.initial_values[idx]);
  for (idx in info.other_values)
    test_value(info.other_values[idx]);
}

// To avoid triggering the slow script dialog, we have to test one
// property at a time.
SimpleTest.waitForExplicitFinish();
var props = [];
for (var prop in gCSSProperties)
  props.push(prop);
props = props.reverse();
function do_one() {
  if (props.length == 0) {
    SimpleTest.finish();
    return;
  }
  test_property(props.pop());
  SimpleTest.executeSoon(do_one);
}
SimpleTest.executeSoon(do_one);

</script>
</pre>
</body>
</html>