tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

serialize-values.html (19827B)


      1 <!DOCTYPE html>
      2 <meta charset="utf-8">
      3 <title>CSSOM serialize values</title>
      4 <link rel="help" href="https://drafts.csswg.org/cssom/#serializing-css-values">
      5 <meta name="author" title="Josh Matthews" href="mailto:josh@joshmatthews.net">
      6 <script src="/resources/testharness.js"></script>
      7 <script src="/resources/testharnessreport.js"></script>
      8 <body>
      9  <div id="log"></div>
     10  <div id="parent"></div>
     11  <script>
     12    function iterable(values) {
     13      var i = 0;
     14      return function() {
     15        if (i < values.length) {
     16          return values[i++];
     17        }
     18        return null;
     19      }
     20    }
     21 
     22    function color() {
     23      var colors = ['black', 'red', 'rgb(50, 75, 100)', 'rgba(5, 7, 10, 0.5)'];
     24      return iterable(colors);
     25    }
     26 
     27    function percentage() {
     28      var values = ["5%", {actual: ".5%", serialized: "0.5%"}];
     29      return iterable(values);
     30    }
     31 
     32    function negative_percentage() {
     33      var values = ["-5%", {actual: "-.5%", serialized: "-0.5%"}];
     34      return iterable(values);
     35    }
     36 
     37    function length() {
     38      var values = ["0px", "1px", {actual: ".1em", serialized: "0.1em"}];
     39      return iterable(values);
     40    }
     41 
     42    function negative_length() {
     43      var values = [{actual: "-0px", serialized: "0px"},
     44                    "-1px", {actual: "-.1em", serialized: "-0.1em"}];
     45      return iterable(values);
     46    }
     47 
     48    function degree() {
     49      var values = ["87deg"];
     50      return iterable(values);
     51    }
     52 
     53    function uri() {
     54      var values = ["url(\"http://localhost/\")",
     55        {actual: "url(http://localhost/)",
     56         serialized: "url(\"http://localhost/\")"}];
     57      return iterable(values);
     58    }
     59 
     60    function border_style() {
     61      var values = ['none', 'hidden', 'dotted', 'dashed', 'solid', 'double', 'groove', 'ridge',
     62                    'inset', 'outset'];
     63      return iterable(values);
     64    }
     65 
     66    function border_style_without_hidden() {
     67      var values = ['none', 'dotted', 'dashed', 'solid', 'double', 'groove', 'ridge',
     68                    'inset', 'outset'];
     69      return iterable(values);
     70    }
     71 
     72    function integer() {
     73      var values = ['0', '101', '-51'];
     74      return iterable(values);
     75    }
     76 
     77    function nonzero_positive_integer() {
     78      var values = ['101'];
     79      return iterable(values);
     80    }
     81 
     82    function shape() {
     83      var values = ['rect(1em, auto, 0.5px, 2000em)'];
     84      return iterable(values);
     85    }
     86 
     87    function string() {
     88      var values = ['"string"', {actual: "'string'", serialized: '"string"'}];
     89      return iterable(values);
     90    }
     91 
     92    function counter() {
     93      var values = ['counter(par-num)',
     94                    { actual: 'counter(par-num, decimal)', serialized: 'counter(par-num)' },
     95                    'counter(par-num, upper-roman)'];
     96      return iterable(values);
     97    }
     98 
     99    function attr() {
    100      var values = ['attr(foo-bar)', 'attr(foo_bar)',
    101                    {actual: "attr(|bar)", serialized: "attr(bar)"},
    102                    {actual: "attr( |bar )", serialized: "attr(bar)"}];
    103      return iterable(values);
    104    }
    105 
    106    function attr_fallback() {
    107      var values = ['attr(foo-bar, "fallback")', 'attr(foo_bar, "fallback")',
    108                    {actual: 'attr(|bar, "fallback")', serialized: 'attr(bar, "fallback")'},
    109                    {actual: 'attr(foo, "")', serialized: 'attr(foo, "")'},
    110                    {actual: 'attr( |foo ,  "" )', serialized: 'attr(foo)'}];
    111      return iterable(values);
    112    }
    113 
    114    function family_name() {
    115      var values = ['Arial', {actual: "'Lucida Grande'", serialized: '"Lucida Grande"'}];
    116      return iterable(values);
    117    }
    118 
    119    function generic_family() {
    120      var values = ['serif', 'sans-serif'];
    121      return iterable(values);
    122    }
    123 
    124    function absolute_size() {
    125      var values = ['xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', 'xx-large'];
    126      return iterable(values);
    127    }
    128 
    129    function relative_size() {
    130      var values = ['larger', 'smaller'];
    131      return iterable(values);
    132    }
    133 
    134    function number() {
    135      var values = ['0', {'actual': '-0', serialized: '0'}, '1000', '-5123', '0.9', '-0.09'];
    136      return iterable(values);
    137    }
    138 
    139    function positive_number() {
    140      var values = ['0', {'actual': '-0', serialized: '0'}, '1000', '0.9'];
    141      return iterable(values);
    142    }
    143 
    144    function generate_inline_style(name, value) {
    145      if (value) {
    146        return {'declaration': name + ": " + value.actual,
    147                'value': value.actual,
    148                'result': value.expected};
    149      }
    150      return null;
    151    }
    152 
    153    var minimal_results = {
    154    };
    155 
    156    function create_result(propertyName, actual, expected) {
    157      var key = propertyName + ": " + expected
    158      if (key in minimal_results)
    159        expected = minimal_results[key]
    160      return {actual: actual, expected: expected}
    161    }
    162 
    163    function all_values(propertyName, values) {
    164      var results = [];
    165      for (var i = 0; i < values.length; i++) {
    166        var value = values[i];
    167        if (typeof value == "function") {
    168          var f = value();
    169          var result;
    170          while ((result = f()) != null) {
    171            if (typeof result == "object" && 'serialized' in result) {
    172              results.push(create_result(propertyName, result.actual, result.serialized));
    173            } else {
    174              results.push(create_result(propertyName, result, result));
    175            }
    176          }
    177        } else if (typeof value == "string") {
    178          results.push(create_result(propertyName, value, value));
    179        } else if (value instanceof Array) {
    180          var subresults = [];
    181          for (var j = 0; j < value.length; j++) {
    182            var subresult = all_values(propertyName, value[j]);
    183            if (!(subresult instanceof Array)) {
    184              subresult = [subresult];
    185            }
    186            subresults.push(subresult);
    187          }
    188          if (subresults.length > 1) {
    189            function choose_slices(vecs) {
    190              if (vecs.length == 1) {
    191                return vecs[0].map(function(v) { return [v]; });
    192              }
    193              var slice_results = [];
    194              var rest = choose_slices(vecs.slice(1, vecs.length));
    195              for (var a = 0; a < vecs[0].length; a++) {
    196                for (var b = 0; b < rest.length; b++) {
    197                  var result = vecs[0][a];
    198                  slice_results.push([result].concat(rest[b]));
    199                }
    200              }
    201              return slice_results;
    202            }
    203 
    204            subresults = choose_slices(subresults).map(function (a) {
    205              var actual = a.map(function(a) { return a.actual });
    206              var expected = a.map(function(a) { return a.expected });
    207              return create_result(propertyName, actual.join(' '), expected.join(' '))
    208            });
    209          }
    210          for (var j = 0; j < subresults.length; j++) {
    211            results = results.concat(subresults[j]);
    212          }
    213        } else if (value instanceof Object && 'serialized' in value) {
    214          results.push(create_result(propertyName, value.actual, value.serialized));
    215        } else if (typeof value == "number") {
    216          results.push(create_result(propertyName, value.toString(), value.toString()));
    217        } else {
    218          throw "unexpected value type: " + typeof(value);
    219        }
    220      }
    221      return results;
    222    }
    223 
    224    function create_value_generator(propertyName, property) {
    225      var results = all_values(propertyName, property.values);
    226      return iterable(results);
    227    }
    228 
    229    function to_idl(property) {
    230      return property.replace(/-\w/g, function(x){return x[1].toUpperCase()});
    231    }
    232 
    233    function run_individual_test(property, generator, initial) {
    234      var elem = document.createElement('div');
    235      document.getElementById('parent').appendChild(elem);
    236      var test_data = generator();
    237      var style = generate_inline_style(property, test_data);
    238      if (!style) {
    239        return false;
    240      }
    241      var t = async_test(style.declaration);
    242 
    243      t.add_cleanup(function() {
    244        document.getElementById('parent').removeChild(elem);
    245      });
    246 
    247      t.step(function() {
    248        elem.setAttribute('style', style.declaration);
    249        var expected = style.result;
    250        var serialized = elem.style[to_idl(property)];
    251        assert_equals(serialized, expected, property + ' raw inline style declaration');
    252        elem.setAttribute('style', '');
    253        elem.style[to_idl(property)] = style.value;
    254        assert_equals(elem.style[to_idl(property)], expected, property + ' style property');
    255      });
    256      t.done();
    257      return true;
    258    }
    259 
    260    function test_property(property) {
    261      var generator = create_value_generator(property[0], property[1]);
    262      while (run_individual_test(property[0], generator, property[1].initial)) {
    263      }
    264    }
    265 
    266    var properties = [
    267      ['background-attachment', {
    268        'values': ['scroll', 'fixed', 'inherit'],
    269        'initial': 'scroll',
    270      }],
    271      ['background-color', {
    272        'values': [color, 'transparent', 'inherit'],
    273        'initial': 'transparent',
    274      }],
    275      ['background-image', {
    276        'values': [uri, 'none', 'inherit'],
    277        'initial': 'none',
    278      }],
    279      ['background-position', {
    280        'values': [[[percentage, negative_percentage, length, negative_length,
    281                     'left', 'center', 'right'],
    282                    [percentage, negative_percentage, length, negative_length,
    283                     'top', 'center', 'bottom']],
    284                   'inherit'],
    285        'initial': '0% 0%',
    286      }],
    287      ['background-repeat', {
    288        'values': ['repeat', 'repeat-x', 'repeat-y', 'no-repeat', 'inherit'],
    289        'initial': 'repeat',
    290      }],
    291      //background
    292      ['border-collapse', {
    293        'values': ['collapse', 'separate', 'inherit'],
    294        'initial': 'separate',
    295      }],
    296      //border-color
    297      ['border-spacing', {
    298        'values': [length, 'inherit'],
    299        'initial': '0',
    300      }],
    301      //border-style
    302      //border-top, border-right, border-bottom, border-left
    303      ['border-top-color', {
    304        'values': [color, 'transparent', 'inherit'],
    305        'initial': 'black', //FIXME
    306      }],
    307      ['border-right-color', {
    308        'values': [color, 'transparent', 'inherit'],
    309        'initial': 'black', //FIXME
    310      }],
    311      ['border-bottom-color', {
    312        'values': [color, 'transparent', 'inherit'],
    313        'initial': 'black', //FIXME
    314      }],
    315      ['border-left-color', {
    316        'values': [color, 'transparent', 'inherit'],
    317        'initial': 'black', //FIXME
    318      }],
    319      ['border-top-style', {
    320        'values': [border_style, 'inherit'],
    321        'initial': null,
    322      }],
    323      ['border-right-style', {
    324        'values': [border_style, 'inherit'],
    325        'initial': null,
    326      }],
    327      ['border-bottom-style', {
    328        'values': [border_style, 'inherit'],
    329        'initial': null,
    330      }],
    331      ['border-left-style', {
    332        'values': [border_style, 'inherit'],
    333        'initial': null,
    334      }],
    335      ['border-top-width', {
    336        'values': ['thin', 'medium', 'thick', length, 'inherit'],
    337        'initial': 'medium',
    338      }],
    339      ['border-right-width', {
    340        'values': ['thin', 'medium', 'thick', length, 'inherit'],
    341        'initial': 'medium',
    342      }],
    343      ['border-bottom-width', {
    344        'values': ['thin', 'medium', 'thick', length, 'inherit'],
    345        'initial': 'medium',
    346      }],
    347      ['border-left-width', {
    348        'values': ['thin', 'medium', 'thick', length, 'inherit'],
    349        'initial': 'medium',
    350      }],
    351      //border-width
    352      //border
    353      ['bottom', {
    354        'values': [length, percentage, 'auto', 'inherit'],
    355        'initial': 'auto',
    356      }],
    357      ['caption-side', {
    358        'values': ['top', 'bottom', 'inherit'],
    359        'initial': 'top',
    360      }],
    361      ['clear', {
    362        'values': ['none', 'left', 'right', 'both', 'inherit'],
    363        'initial': 'none',
    364      }],
    365      ['clip', {
    366        'values': [shape, 'auto', 'inherit'],
    367        'initial': 'auto',
    368      }],
    369      ['color', {
    370        'values': [color, 'inherit'],
    371        'initial': 'black', //FIXME depends on user agent
    372      }],
    373      ['content', {
    374        'values': ['normal', 'none', string, uri, counter, attr, attr_fallback, 'inherit'], //FIXME
    375        'initial': 'normal',
    376      }],
    377      //counter-increment
    378      //counter-reset
    379      ['cursor', {
    380        'values': [ 'auto', 'crosshair', 'default', 'pointer', 'move', 'e-resize', 'ne-resize',
    381                    'nw-resize', 'n-resize', 'se-resize', 'sw-resize', 's-resize', 'w-resize',
    382                    'text', 'wait', 'help', 'progress', 'inherit'],
    383        'initial': 'auto',
    384      }],
    385      ['direction', {
    386        'values': ['ltr', 'rtl', 'inherit'],
    387        'initial': 'ltr',
    388      }],
    389      ['display', {
    390        'values': ['inline', 'block', 'list-item', 'inline-block', 'table', 'inline-table',
    391                   'table-row-group', 'table-header-group', 'table-footer-group', 'table-row',
    392                   'table-column-group', 'table-column', 'table-cell', 'table-caption', 'none',
    393                   'inherit'],
    394        'initial': 'inline',
    395      }],
    396      ['empty-cells', {
    397         'values': ['show', 'hide', 'inherit'],
    398         'initial': 'show',
    399      }],
    400      ['float', {
    401        'values': ['left', 'right', 'none', 'inherit'],
    402        'initial': 'none',
    403        'property': 'cssFloat',
    404      }],
    405      ['font-family', {
    406        'values': [family_name, generic_family, 'inherit'],
    407        'initial': 'sans-serif', //FIXME depends on user agent
    408      }],
    409      ['font-size', {
    410        'values': [absolute_size, relative_size, length, percentage, 'inherit'],
    411        'initial': 'medium',
    412      }],
    413      ['font-style', {
    414        'values': ['normal', 'italic', 'oblique', 'inherit'],
    415        'initial': 'normal',
    416      }],
    417      ['font-variant', {
    418        'values': ['normal', 'small-caps', 'inherit'],
    419        'initial': 'normal',
    420      }],
    421      ['font-weight', {
    422        'values': ['normal', 'bold', 'bolder', 'lighter', 100, 200, 300, 400, 500, 600,
    423                   700, 800, 900, 'inherit'],
    424        'initial': 'normal',
    425      }],
    426      //font
    427      ['height', {
    428        'values': [length, percentage, 'auto', 'inherit'],
    429        'initial': 'auto',
    430      }],
    431      ['left', {
    432        'values': [length, percentage, 'auto', 'inherit'],
    433        'initial': 'auto',
    434      }],
    435      ['letter-spacing', {
    436        'values': ['normal', length, 'inherit'],
    437        'initial': 'normal',
    438      }],
    439      ['line-height', {
    440        'values': ['normal', positive_number, length, percentage, 'inherit'],
    441        'initial': 'normal',
    442      }],
    443      ['list-style-image', {
    444        'values': [uri, 'none', 'inherit'],
    445        'initial': 'none',
    446      }],
    447      ['list-style-position', {
    448        'values': ['inside', 'outside', 'inherit'],
    449        'initial': 'outside',
    450      }],
    451      ['list-style-type', {
    452        'values': ['disc', 'circle', 'square', 'disclosure-open', 'disclosure-closed',
    453                   'decimal', 'decimal-leading-zero', 'lower-roman',
    454                   'upper-roman', 'lower-greek', 'lower-latin', 'upper-latin', 'armenian', 'georgian',
    455                   'lower-alpha', 'upper-alpha', 'none', 'inherit'],
    456        'initial': 'disc',
    457      }],
    458      //list-style
    459      ['margin-right', {
    460        'values': [length, percentage, 'auto', 'inherit'],
    461        'initial': 0,
    462      }],
    463      ['margin-left', {
    464        'values': [length, percentage, 'auto', 'inherit'],
    465        'initial': 0,
    466      }],
    467      ['margin-top', {
    468        'values': [length, percentage, 'auto', 'inherit'],
    469        'initial': 0,
    470      }],
    471      ['margin-bottom', {
    472        'values': [length, percentage, 'auto', 'inherit'],
    473        'initial': 0,
    474      }],
    475      //margin
    476      ['max-height', {
    477        'values': [length, percentage, 'none', 'inherit'],
    478        'initial': 'none',
    479      }],
    480      ['max-width', {
    481        'values': [length, percentage, 'none', 'inherit'],
    482        'initial': 'none',
    483      }],
    484      ['min-height', {
    485        'values': [length, percentage, 'inherit'],
    486        'initial': 0,
    487      }],
    488      ['min-width', {
    489        'values': [length, percentage, 'inherit'],
    490        'initial': 0,
    491      }],
    492      ['orphans', {
    493        'values': [nonzero_positive_integer, 'inherit'],
    494        'initial': 2,
    495      }],
    496      ['outline-color', {
    497        'values': [color, 'invert', 'inherit'],
    498        'initial': 'invert',
    499      }],
    500      ['outline-style', {
    501        'values': [border_style_without_hidden, 'inherit'],
    502        'initial': 'none',
    503      }],
    504      ['outline-width', {
    505        'values': ['thin', 'medium', 'thick', length, 'inherit'],
    506        'initial': 'medium',
    507      }],
    508      //outline
    509      ['overflow', {
    510        'values': ['visible', 'hidden', 'scroll', 'auto', 'inherit'],
    511        'initial': 'visible',
    512      }],
    513      ['padding-top', {
    514        'values': [length, percentage, 'inherit'],
    515        'initial': 0,
    516      }],
    517      ['padding-right', {
    518        'values': [length, percentage, 'inherit'],
    519        'initial': 0,
    520      }],
    521      ['padding-bottom', {
    522        'values': [length, percentage, 'inherit'],
    523        'initial': 0,
    524      }],
    525      ['padding-left', {
    526        'values': [length, percentage, 'inherit'],
    527        'initial': 0,
    528      }],
    529      //padding
    530      ['page-break-after', {
    531        'values': ['auto', 'always', 'avoid', 'left', 'right', 'inherit'],
    532        'initial': 'auto',
    533      }],
    534      ['page-break-before', {
    535        'values': ['auto', 'always', 'avoid', 'left', 'right', 'inherit'],
    536        'initial': 'auto',
    537      }],
    538      ['page-break-inside', {
    539        'values': ['avoid', 'auto', 'inherit'],
    540        'initial': 'auto',
    541      }],
    542      ['position', {
    543        'values': ['static', 'relative', 'absolute', 'fixed', 'inherit'],
    544        'initial': 'static',
    545      }],
    546      //FIXME quotes
    547      ['right', {
    548        'values': [length, percentage, 'auto', 'inherit'],
    549        'initial': 'auto',
    550      }],
    551      ['table-layout', {
    552        'values': ['auto', 'fixed', 'inherit'],
    553        'initial': 'auto',
    554      }],
    555      ['text-align', {
    556        'values': ['left', 'right', 'center', 'justify', 'inherit'],
    557        'initial': null,
    558      }],
    559      ['text-decoration', {
    560        'values': ['none', 'underline', 'overline', 'line-through', 'blink', 'inherit'],
    561        'initial': 'none',
    562      }],
    563      ['text-indent', {
    564        'values': [length, percentage, 'inherit'],
    565        'initial': 0,
    566      }],
    567      ['text-transform', {
    568        'values': ['capitalize', 'uppercase', 'lowercase', 'none', 'inherit'],
    569        'initial': 'none',
    570      }],
    571      ['top', {
    572        'values': [length, percentage, 'auto', 'inherit'],
    573        'initial': 'auto',
    574      }],
    575      ['unicode-bidi', {
    576        'values': ['normal', 'embed', 'bidi-override', 'inherit'],
    577        'initial': 'normal',
    578      }],
    579      ['vertical-align', {
    580        'values': ['baseline', 'sub', 'super', 'top', 'text-top', 'middle', 'bottom', 'text-bottom',
    581                   percentage, length, 'inherit'],
    582        'initial': 'baseline',
    583      }],
    584      ['visibility', {
    585        'values': ['visible', 'hidden', 'collapse', 'inherit'],
    586        'initial': 'visible',
    587      }],
    588      ['white-space', {
    589        'values': ['normal', 'pre', 'nowrap', 'pre-wrap', 'pre-line', 'inherit'],
    590        'initial': 'normal',
    591      }],
    592      ['widows', {
    593        'values': [nonzero_positive_integer, 'inherit'],
    594        'initial': 2,
    595      }],
    596      ['width', {
    597        'values': [length, percentage, 'auto', 'inherit'],
    598        'initial': 'auto',
    599      }],
    600      ['word-spacing', {
    601        'values': ['normal', length, 'inherit'],
    602        'initial': 'normal',
    603      }],
    604      ['z-index', {
    605        'values': ['auto', integer, 'inherit'],
    606        'initial': 'auto',
    607      }],
    608    ]
    609 
    610    for (var index = 0; index < properties.length; index++) {
    611      test_property(properties[index]);
    612    }
    613  </script>
    614 </body>