layout/style/test/flexbox_layout_testcases.js

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

     1 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set ts=2 sw=2 sts=2 et: */
     4 /*
     5  * This Source Code is subject to the terms of the Mozilla Public License
     6  * version 2.0 (the "License"). You can obtain a copy of the License at
     7  * http://mozilla.org/MPL/2.0/.
     8  */
    10 /**
    11  * For the purposes of this test, flex items are specified as a hash with a
    12  * hash-entry for each CSS property that is to be set.  In these per-property
    13  * entries, the key is the property-name, and the value can be either of the
    14  * following:
    15  *  (a) the property's specified value (which indicates that we don't need to
    16  *      bother checking the computed value of this particular property)
    17  *  ...OR...
    18  *  (b) an array with 2-3 entries...
    19  *        [specifiedValue, expectedComputedValue (, epsilon) ]
    20  *      ...which indicates that the property's computed value should be
    21  *      checked.  The array's first entry (for the specified value) may be
    22  *      null; this means that no value should be explicitly specified for this
    23  *      property. The second entry is the property's expected computed
    24  *      value. The third (optional) entry is an epsilon value, which allows for
    25  *      fuzzy equality when testing the computed value.
    26  *
    27  * To allow these testcases to be re-used in both horizontal and vertical
    28  * flex containers, we specify "width"/"min-width"/etc. using the aliases
    29  * "_main-size", "_min-main-size", etc.  The test code can map these
    30  * placeholder names to their corresponding property-names using the maps
    31  * defined below -- gRowPropertyMapping, gColumnPropertyMapping, etc.
    32  *
    33  * If the testcase needs to customize its flex container at all (e.g. by
    34  * specifying a custom container-size), it can do so by including a hash
    35  * called "container_properties", with propertyName:propertyValue mappings.
    36  * (This hash can use aliased property-names like "_main-size" as well.)
    37  */
    39 // The standard main-size we'll use for our flex container when setting up
    40 // the testcases defined below:
    41 var gDefaultFlexContainerSize = "200px";
    43 // Left-to-right versions of placeholder property-names used in
    44 // testcases below:
    45 var gRowPropertyMapping =
    46 {
    47   "_main-size":               "width",
    48   "_min-main-size":           "min-width",
    49   "_max-main-size":           "max-width",
    50   "_border-main-start-width": "border-left-width",
    51   "_border-main-end-width":   "border-right-width",
    52   "_padding-main-start":      "padding-left",
    53   "_padding-main-end":        "padding-right",
    54   "_margin-main-start":       "margin-left",
    55   "_margin-main-end":         "margin-right"
    56 };
    58 // Right-to-left versions of placeholder property-names used in
    59 // testcases below:
    60 var gRowReversePropertyMapping =
    61 {
    62   "_main-size":               "width",
    63   "_min-main-size":           "min-width",
    64   "_max-main-size":           "max-width",
    65   "_border-main-start-width": "border-right-width",
    66   "_border-main-end-width":   "border-left-width",
    67   "_padding-main-start":      "padding-right",
    68   "_padding-main-end":        "padding-left",
    69   "_margin-main-start":       "margin-right",
    70   "_margin-main-end":         "margin-left"
    71 };
    73 // Top-to-bottom versions of placeholder property-names used in
    74 // testcases below:
    75 var gColumnPropertyMapping =
    76 {
    77   "_main-size":               "height",
    78   "_min-main-size":           "min-height",
    79   "_max-main-size":           "max-height",
    80   "_border-main-start-width": "border-top-width",
    81   "_border-main-end-width":   "border-bottom-width",
    82   "_padding-main-start":      "padding-top",
    83   "_padding-main-end":        "padding-bottom",
    84   "_margin-main-start":       "margin-top",
    85   "_margin-main-end":         "margin-bottom"
    86 };
    88 // Bottom-to-top versions of placeholder property-names used in
    89 // testcases below:
    90 var gColumnReversePropertyMapping =
    91 {
    92   "_main-size":               "height",
    93   "_min-main-size":           "min-height",
    94   "_max-main-size":           "max-height",
    95   "_border-main-start-width": "border-bottom-width",
    96   "_border-main-end-width":   "border-top-width",
    97   "_padding-main-start":      "padding-bottom",
    98   "_padding-main-end":        "padding-top",
    99   "_margin-main-start":       "margin-bottom",
   100   "_margin-main-end":         "margin-top"
   101 };
   103 // The list of actual testcase definitions:
   104 var gFlexboxTestcases =
   105 [
   106  // No flex properties specified --> should just use 'width' for sizing
   107  {
   108    items:
   109      [
   110        { "_main-size": [ "40px", "40px" ] },
   111        { "_main-size": [ "65px", "65px" ] },
   112      ]
   113  },
   114  // flex-basis is specified:
   115  {
   116    items:
   117      [
   118        { "flex-basis": "50px",
   119          "_main-size": [ null,  "50px" ]
   120        },
   121        {
   122          "flex-basis": "20px",
   123          "_main-size": [ null, "20px" ]
   124        },
   125      ]
   126  },
   127  // flex-basis is *large* -- sum of flex-basis values is > flex container size:
   128  // (w/ 0 flex-shrink so we don't shrink):
   129  {
   130    items:
   131      [
   132        {
   133          "flex": "0 0 150px",
   134          "_main-size": [ null, "150px" ]
   135        },
   136        {
   137          "flex": "0 0 90px",
   138          "_main-size": [ null, "90px" ]
   139        },
   140      ]
   141  },
   142  // flex-basis is *large* -- each flex-basis value is > flex container size:
   143  // (w/ 0 flex-shrink so we don't shrink):
   144  {
   145    items:
   146      [
   147        {
   148          "flex": "0 0 250px",
   149          "_main-size": [ null, "250px" ]
   150        },
   151        {
   152          "flex": "0 0 400px",
   153          "_main-size": [ null, "400px" ]
   154        },
   155      ]
   156  },
   157  // flex-basis has percentage value:
   158  {
   159    items:
   160      [
   161        {
   162          "flex-basis": "30%",
   163          "_main-size": [ null, "60px" ]
   164        },
   165        {
   166          "flex-basis": "45%",
   167          "_main-size": [ null, "90px" ]
   168        },
   169      ]
   170  },
   171  // flex-basis has calc(percentage) value:
   172  {
   173    items:
   174      [
   175        {
   176          "flex-basis": "calc(20%)",
   177          "_main-size": [ null, "40px" ]
   178        },
   179        {
   180          "flex-basis": "calc(80%)",
   181          "_main-size": [ null, "160px" ]
   182        },
   183      ]
   184  },
   185  // flex-basis has calc(percentage +/- length) value:
   186  {
   187    items:
   188      [
   189        {
   190          "flex-basis": "calc(10px + 20%)",
   191          "_main-size": [ null, "50px" ]
   192        },
   193        {
   194          "flex-basis": "calc(60% - 1px)",
   195          "_main-size": [ null, "119px" ]
   196        },
   197      ]
   198  },
   199  // flex-grow is specified:
   200  {
   201    items:
   202      [
   203        {
   204          "flex": "1",
   205          "_main-size": [ null,  "60px" ]
   206        },
   207        {
   208          "flex": "2",
   209          "_main-size": [ null, "120px" ]
   210        },
   211        {
   212          "flex": "0 20px",
   213          "_main-size": [ null, "20px" ]
   214        }
   215      ]
   216  },
   217  // Same ratio as prev. testcase; making sure we handle float inaccuracy
   218  {
   219    items:
   220      [
   221        {
   222          "flex": "100000",
   223          "_main-size": [ null,  "60px" ]
   224        },
   225        {
   226          "flex": "200000",
   227          "_main-size": [ null, "120px" ]
   228        },
   229        {
   230          "flex": "0.000001 20px",
   231          "_main-size": [ null,  "20px" ]
   232        }
   233      ]
   234  },
   235  // Same ratio as prev. testcase, but with items cycled and w/
   236  // "flex: none" & explicit size instead of "flex: 0 20px"
   237  {
   238    items:
   239      [
   240        {
   241          "flex": "none",
   242          "_main-size": [ "20px", "20px" ]
   243        },
   244        {
   245          "flex": "1",
   246          "_main-size": [ null,   "60px" ]
   247        },
   248        {
   249          "flex": "2",
   250          "_main-size": [ null,  "120px" ]
   251        }
   252      ]
   253  },
   255  // ...and now with flex-grow:[huge] to be sure we handle infinite float values
   256  // gracefully.
   257  {
   258    items:
   259      [
   260        {
   261          "flex": "9999999999999999999999999999999999999999999999999999999",
   262          "_main-size": [ null,  "200px" ]
   263        },
   264      ]
   265  },
   266  {
   267    items:
   268      [
   269        {
   270          "flex": "9999999999999999999999999999999999999999999999999999999",
   271          "_main-size": [ null,  "50px" ]
   272        },
   273        {
   274          "flex": "9999999999999999999999999999999999999999999999999999999",
   275          "_main-size": [ null,  "50px" ]
   276        },
   277        {
   278          "flex": "9999999999999999999999999999999999999999999999999999999",
   279          "_main-size": [ null,  "50px" ]
   280        },
   281        {
   282          "flex": "9999999999999999999999999999999999999999999999999999999",
   283          "_main-size": [ null,  "50px" ]
   284        },
   285      ]
   286  },
   287  {
   288    items:
   289      [
   290        {
   291          "flex": "99999999999999999999999999999999999",
   292          "_main-size": [ null,  "50px" ]
   293        },
   294        {
   295          "flex": "99999999999999999999999999999999999",
   296          "_main-size": [ null,  "50px" ]
   297        },
   298        {
   299          "flex": "99999999999999999999999999999999999",
   300          "_main-size": [ null,  "50px" ]
   301        },
   302        {
   303          "flex": "99999999999999999999999999999999999",
   304          "_main-size": [ null,  "50px" ]
   305        },
   306      ]
   307  },
   309  // And now, some testcases to check that we handle float accumulation error
   310  // gracefully.
   312  // First, a testcase with just a custom-sized huge container, to be sure we'll
   313  // be able to handle content on that scale, in the subsequent more-complex
   314  // testcases:
   315  {
   316    container_properties:
   317    {
   318      "_main-size": "9000000px"
   319    },
   320    items:
   321      [
   322        {
   323          "flex": "1",
   324          "_main-size": [ null,  "9000000px" ]
   325        },
   326      ]
   327  },
   328  // ...and now with two flex items dividing up that container's huge size:
   329  {
   330    container_properties:
   331    {
   332      "_main-size": "9000000px"
   333    },
   334    items:
   335      [
   336        {
   337          "flex": "2",
   338          "_main-size": [ null,  "6000000px" ]
   339        },
   340        {
   341          "flex": "1",
   342          "_main-size": [ null,  "3000000px" ]
   343        },
   344      ]
   345  },
   347  // OK, now to actually test accumulation error. Below, we have six flex items
   348  // splitting up the container's size, with huge differences between flex
   349  // weights.  For simplicity, I've set up the weights so that they sum exactly
   350  // to the container's size in px. So 1 unit of flex *should* get you 1px.
   351  //
   352  // NOTE: The expected computed "_main-size" values for the flex items below
   353  // appear to add up to more than their container's size, which would suggest
   354  // that they overflow their container unnecessarily. But they don't actually
   355  // overflow -- this discrepancy is simply because Gecko's code for reporting
   356  // computed-sizes rounds to 6 significant figures (in particular, the method
   357  // (nsTSubstring_CharT::AppendFloat() does this).  Internally, in app-units,
   358  // the child frames' main-sizes add up exactly to the container's main-size,
   359  // as you'd hope & expect.
   360  {
   361    container_properties:
   362    {
   363      "_main-size": "9000000px"
   364    },
   365    items:
   366      [
   367        {
   368          "flex": "3000000",
   369          "_main-size": [ null,  "3000000px" ]
   370        },
   371        {
   372          "flex": "1",
   373          "_main-size": [ null,  "1px" ]
   374        },
   375        {
   376          "flex": "1",
   377          "_main-size": [ null,  "1px" ]
   378        },
   379        {
   380          "flex": "2999999",
   381          // NOTE: Expected value is off slightly, from float error when
   382          // resolving flexible lengths & when generating computed value string:
   383          "_main-size": [ null,  "3000000px" ]
   384        },
   385        {
   386          "flex": "2999998",
   387          // NOTE: Expected value is off slightly, from float error when
   388          // resolving flexible lengths & when generating computed value string:
   389          "_main-size": [ null,  "3000000px" ]
   390        },
   391        {
   392          "flex": "1",
   393          "_main-size": [ null,  "1px", 0.2 ]
   394        },
   395      ]
   396  },
   397  // Same flex items as previous testcase, but now reordered such that the items
   398  // with tiny flex weights are all listed last:
   399  {
   400    container_properties:
   401    {
   402      "_main-size": "9000000px"
   403    },
   404    items:
   405      [
   406        {
   407          "flex": "3000000",
   408          "_main-size": [ null,  "3000000px" ]
   409        },
   410        {
   411          "flex": "2999999",
   412          // NOTE: Expected value is off slightly, from float error when
   413          // resolving flexible lengths & when generating computed value string:
   414          "_main-size": [ null,  "3000000px" ]
   415        },
   416        {
   417          "flex": "2999998",
   418          // NOTE: Expected value is off slightly, from float error when
   419          // resolving flexible lengths & when generating computed value string:
   420          "_main-size": [ null,  "3000000px" ]
   421        },
   422        {
   423          "flex": "1",
   424          "_main-size": [ null,  "1px", 0.2 ]
   425        },
   426        {
   427          "flex": "1",
   428          "_main-size": [ null,  "1px", 0.2 ]
   429        },
   430        {
   431          "flex": "1",
   432          "_main-size": [ null,  "1px", 0.2 ]
   433        },
   434      ]
   435  },
   436  // Same flex items as previous testcase, but now reordered such that the items
   437  // with tiny flex weights are all listed first:
   438  {
   439    container_properties:
   440    {
   441      "_main-size": "9000000px"
   442    },
   443    items:
   444      [
   445        {
   446          "flex": "1",
   447          // NOTE: Expected value is off slightly, from float error when
   448          // resolving flexible lengths:
   449          "_main-size": [ null,  "1px", 0.2 ]
   450        },
   451        {
   452          "flex": "1",
   453          // NOTE: Expected value is off slightly, from float error when
   454          // resolving flexible lengths:
   455          "_main-size": [ null,  "1px", 0.2 ]
   456        },
   457        {
   458          "flex": "1",
   459          // NOTE: Expected value is off slightly, from float error when
   460          // resolving flexible lengths:
   461          "_main-size": [ null,  "1px", 0.2 ]
   462        },
   463        {
   464          "flex": "3000000",
   465          "_main-size": [ null,  "3000000px" ]
   466        },
   467        {
   468          "flex": "2999999",
   469          // NOTE: Expected value is off slightly, from float error when
   470          // resolving flexible lengths & when generating computed value string:
   471          "_main-size": [ null,  "3000000px" ]
   472        },
   473        {
   474          "flex": "2999998",
   475          // NOTE: Expected value is off slightly, from float error when
   476          // resolving flexible lengths & when generating computed value string:
   477          "_main-size": [ null,  "3000000px" ]
   478        },
   479      ]
   480  },
   482  // Trying "flex: auto" (== "1 1 auto") w/ a mix of flex-grow/flex-basis values
   483  {
   484    items:
   485      [
   486        {
   487          "flex": "auto",
   488          "_main-size": [ null, "45px" ]
   489        },
   490        {
   491          "flex": "2",
   492          "_main-size": [ null, "90px" ]
   493        },
   494        {
   495          "flex": "20px 1 0",
   496          "_main-size": [ null, "65px" ]
   497        }
   498      ]
   499  },
   500  // Same as previous, but with items cycled & different syntax
   501  {
   502    items:
   503      [
   504        {
   505          "flex": "20px",
   506          "_main-size": [ null, "65px" ]
   507        },
   508        {
   509          "flex": "1",
   510          "_main-size": [ null, "45px" ]
   511        },
   512        {
   513          "flex": "2",
   514          "_main-size": [ null, "90px" ]
   515        }
   516      ]
   517  },
   518  {
   519    items:
   520      [
   521        {
   522          "flex": "2",
   523          "_main-size": [ null,  "100px" ],
   524          "border": "0px dashed",
   525          "_border-main-start-width": [ "5px",  "5px" ],
   526          "_border-main-end-width": [ "15px", "15px" ],
   527          "_margin-main-start": [ "22px", "22px" ],
   528          "_margin-main-end": [ "8px", "8px" ]
   529        },
   530        {
   531          "flex": "1",
   532          "_main-size": [ null,  "50px" ],
   533          "_margin-main-start": [ "auto", "0px" ],
   534          "_padding-main-end": [ "auto", "0px" ],
   535        }
   536      ]
   537  },
   538  // Test negative flexibility:
   540  // Basic testcase: just 1 item (relying on initial "flex-shrink: 1") --
   541  // should shrink to container size.
   542  {
   543    items:
   544      [
   545        { "_main-size": [ "400px",  "200px" ] },
   546      ],
   547  },
   548  // ...and now with a "flex" specification and a different flex-shrink value:
   549  {
   550    items:
   551      [
   552        {
   553          "flex": "4 2 250px",
   554          "_main-size": [ null,  "200px" ]
   555        },
   556      ],
   557  },
   558  // ...and now with multiple items, which all shrink proportionally (by 50%)
   559  // to fit to the container, since they have the same (initial) flex-shrink val
   560  {
   561    items:
   562      [
   563        { "_main-size": [ "80px",   "40px" ] },
   564        { "_main-size": [ "40px",   "20px" ] },
   565        { "_main-size": [ "30px",   "15px" ] },
   566        { "_main-size": [ "250px", "125px" ] },
   567      ]
   568  },
   569  // ...and now with positive flexibility specified. (should have no effect, so
   570  // everything still shrinks by the same proportion, since the flex-shrink
   571  // values are all the same).
   572  {
   573    items:
   574      [
   575        {
   576          "flex": "4 3 100px",
   577          "_main-size": [ null,  "80px" ]
   578        },
   579        {
   580          "flex": "5 3 50px",
   581          "_main-size": [ null,  "40px" ]
   582        },
   583        {
   584          "flex": "0 3 100px",
   585          "_main-size": [ null, "80px" ]
   586        }
   587      ]
   588  },
   589  // ...and now with *different* flex-shrink values:
   590  {
   591    items:
   592      [
   593        {
   594          "flex": "4 2 50px",
   595          "_main-size": [ null,  "30px" ]
   596        },
   597        {
   598          "flex": "5 3 50px",
   599          "_main-size": [ null,  "20px" ]
   600        },
   601        {
   602          "flex": "0 0 150px",
   603          "_main-size": [ null, "150px" ]
   604        }
   605      ]
   606  },
   607  // Same ratio as prev. testcase; making sure we handle float inaccuracy
   608  {
   609    items:
   610      [
   611        {
   612          "flex": "4 20000000 50px",
   613          "_main-size": [ null,  "30px" ]
   614        },
   615        {
   616          "flex": "5 30000000 50px",
   617          "_main-size": [ null,  "20px" ]
   618        },
   619        {
   620          "flex": "0 0.0000001 150px",
   621          "_main-size": [ null, "150px" ]
   622        }
   623      ]
   624  },
   625  // Another "different flex-shrink values" testcase:
   626  {
   627    items:
   628      [
   629        {
   630          "flex": "4 2 115px",
   631          "_main-size": [ null,  "69px" ]
   632        },
   633        {
   634          "flex": "5 1 150px",
   635          "_main-size": [ null,  "120px" ]
   636        },
   637        {
   638          "flex": "1 4 30px",
   639          "_main-size": [ null,  "6px" ]
   640        },
   641        {
   642          "flex": "1 0 5px",
   643          "_main-size": [ null, "5px" ]
   644        },
   645      ]
   646  },
   648  // ...and now with min-size (clamping the effects of flex-shrink on one item):
   649  {
   650    items:
   651      [
   652        {
   653          "flex": "4 5 75px",
   654          "_min-main-size": "50px",
   655          "_main-size": [ null,  "50px" ],
   656        },
   657        {
   658          "flex": "5 5 100px",
   659          "_main-size": [ null,  "62.5px" ]
   660        },
   661        {
   662          "flex": "0 4 125px",
   663          "_main-size": [ null, "87.5px" ]
   664        }
   665      ]
   666  },
   668  // Test a min-size that's much larger than initial preferred size, but small
   669  // enough that our flexed size pushes us over it:
   670  {
   671    items:
   672      [
   673        {
   674          "flex": "auto",
   675          "_min-main-size": "110px",
   676          "_main-size": [ "50px",  "125px" ]
   677        },
   678        {
   679          "flex": "auto",
   680          "_main-size": [ null, "75px" ]
   681        }
   682      ]
   683  },
   685  // Test a min-size that's much larger than initial preferred size, and is
   686  // even larger than our positively-flexed size, so that we have to increase it
   687  // (as a 'min violation') after we've flexed.
   688  {
   689    items:
   690      [
   691        {
   692          "flex": "auto",
   693          "_min-main-size": "150px",
   694          "_main-size": [ "50px",  "150px" ]
   695        },
   696        {
   697          "flex": "auto",
   698          "_main-size": [ null, "50px" ]
   699        }
   700      ]
   701  },
   703  // Test min-size on multiple items simultaneously:
   704  {
   705    items:
   706      [
   707        {
   708          "flex": "auto",
   709          "_min-main-size": "20px",
   710          "_main-size": [ null,  "20px" ]
   711        },
   712        {
   713          "flex": "9 auto",
   714          "_min-main-size": "150px",
   715          "_main-size": [ "50px",  "180px" ]
   716        },
   717      ]
   718  },
   719  {
   720    items:
   721      [
   722        {
   723          "flex": "1 1 0px",
   724          "_min-main-size": "90px",
   725          "_main-size": [ null, "90px" ]
   726        },
   727        {
   728          "flex": "1 1 0px",
   729          "_min-main-size": "80px",
   730          "_main-size": [ null, "80px" ]
   731        },
   732        {
   733          "flex": "1 1 40px",
   734          "_main-size": [ null, "30px" ]
   735        }
   736      ]
   737  },
   739  // Test a case where _min-main-size will be violated on different items in
   740  // successive iterations of the "resolve the flexible lengths" loop
   741  {
   742    items:
   743      [
   744        {
   745          "flex": "1 2 100px",
   746          "_min-main-size": "90px",
   747          "_main-size": [ null, "90px" ]
   748        },
   749        {
   750          "flex": "1 1 100px",
   751          "_min-main-size": "70px",
   752          "_main-size": [ null, "70px" ]
   753        },
   754        {
   755          "flex": "1 1 100px",
   756          "_main-size": [ null, "40px" ]
   757        }
   758      ]
   759  },
   761  // Test some cases that have a min-size violation on one item and a
   762  // max-size violation on another:
   764  // Here, both items initially grow to 100px. That violates both
   765  // items' sizing constraints (it's smaller than the min-size and larger than
   766  // the max-size), so we clamp both of them and sum the clamping-differences:
   767  //
   768  //   (130px - 100px) + (50px - 100px) = (30px) + (-50px) = -20px
   769  //
   770  // This sum is negative, so (per spec) we freeze the item that had its
   771  // max-size violated (the second one) and restart the algorithm.  This time,
   772  // all the available space (200px - 50px = 150px) goes to the not-yet-frozen
   773  // first item, and that puts it above its min-size, so all is well.
   774  {
   775    items:
   776      [
   777        {
   778          "flex": "auto",
   779          "_min-main-size": "130px",
   780          "_main-size": [ null, "150px" ]
   781        },
   782        {
   783          "flex": "auto",
   784          "_max-main-size": "50px",
   785          "_main-size": [ null,  "50px" ]
   786        },
   787      ]
   788  },
   790  // As above, both items initially grow to 100px, and that violates both items'
   791  // constraints. However, now the sum of the clamping differences is:
   792  //
   793  //   (130px - 100px) + (80px - 100px) = (30px) + (-20px) = 10px
   794  //
   795  // This sum is positive, so (per spec) we freeze the item that had its
   796  // min-size violated (the first one) and restart the algorithm. This time,
   797  // all the available space (200px - 130px = 70px) goes to the not-yet-frozen
   798  // second item, and that puts it below its max-size, so all is well.
   799  {
   800    items:
   801      [
   802        {
   803          "flex": "auto",
   804          "_min-main-size": "130px",
   805          "_main-size": [ null, "130px" ]
   806        },
   807        {
   808          "flex": "auto",
   809          "_max-main-size": "80px",
   810          "_main-size": [ null,  "70px" ]
   811        },
   812      ]
   813  },
   815  // As above, both items initially grow to 100px, and that violates both items'
   816  // constraints. So we clamp both items and sum the clamping differences to
   817  // see what to do next.  The sum is:
   818  //
   819  //   (80px - 100px) + (120px - 100px) = (-20px) + (20px) = 0px
   820  //
   821  // Per spec, if the sum is 0, we're done -- we leave both items at their
   822  // clamped sizes.
   823  {
   824    items:
   825      [
   826        {
   827          "flex": "auto",
   828          "_max-main-size": "80px",
   829          "_main-size": [ null,  "80px" ]
   830        },
   831        {
   832          "flex": "auto",
   833          "_min-main-size": "120px",
   834          "_main-size": [ null, "120px" ]
   835        },
   836      ]
   837  },
   838 ];

mercurial