flex
Version:
Implementation CSS layout using pure Reason - powered by css-layout project.
1,404 lines • 74.7 kB
JavaScript
/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
// In the fixed point encoding of layout/style values, each field is measured in hundredths of pixels.
let unitsPerPixel = 100;
let zerosPerPixel = 2;
let intUnitsFromPixels = (v) => v != null ? '' + (v * unitsPerPixel) : '0';
let floatUnitsFromPixels = (v) => v != null ? '' + (v) + '.0' : '0.0';
let testDataToIntEncoding = (v) => v != null ? '' + (v) : '0';
let testDataToFloatEncoding = (v) => {
let divided = '' + (v / unitsPerPixel);
if (divided.indexOf('.') !== -1) {
return divided;
} else {
return divided + '.0';
}
};
/**
* Test style data is in a JSON form that resembles the Reason records, but
* string form where necessary (such as 'FlexGrow' instead of FlexGrow). Test
* data should be in the form of fixed integer encoding. We will convert it to
* floating point as part of the test generation process if needed.
*/
window.testData =
{"flex_grow_within_max_width":{"style":{"width":20000,"height":10000},"children":{"child0":{"style":{"flexDirection":"Row","maxWidth":10000},"children":{"child0":{"style":{"height":2000,"flexGrow":"1"}}}}}},"flex_grow_within_constrained_max_width":{"style":{"width":20000,"height":10000},"children":{"child0":{"style":{"flexDirection":"Row","maxWidth":30000},"children":{"child0":{"style":{"height":2000,"flexGrow":"1"}}}}}},"justify_content_overflow_min_max":{"style":{"minHeight":10000,"maxHeight":11000,"justifyContent":"JustifyCenter"},"children":{"child0":{"style":{"width":5000,"height":5000}},"child1":{"style":{"width":5000,"height":5000}},"child2":{"style":{"width":5000,"height":5000}}}},"justify_content_min_max":{"style":{"maxHeight":20000,"minHeight":10000,"width":10000,"justifyContent":"JustifyCenter"},"children":{"child0":{"style":{"width":6000,"height":6000}}}},"align_items_min_max":{"style":{"maxWidth":20000,"minWidth":10000,"height":10000,"alignItems":"AlignCenter"},"children":{"child0":{"style":{"width":6000,"height":6000}}}},"align_items_stretch":{"style":{"width":10000,"height":10000},"children":{"child0":{"style":{"height":1000}}}},"align_items_center":{"style":{"width":10000,"height":10000,"alignItems":"AlignCenter"},"children":{"child0":{"style":{"height":1000,"width":1000}}}},"align_items_flex_start":{"style":{"width":10000,"height":10000,"alignItems":"AlignFlexStart"},"children":{"child0":{"style":{"height":1000,"width":1000}}}},"align_items_flex_end":{"style":{"width":10000,"height":10000,"alignItems":"AlignFlexEnd"},"children":{"child0":{"style":{"height":1000,"width":1000}}}},"align_self_center":{"style":{"width":10000,"height":10000},"children":{"child0":{"style":{"height":1000,"width":1000,"alignSelf":"AlignCenter"}}}},"align_self_flex_end":{"style":{"width":10000,"height":10000},"children":{"child0":{"style":{"height":1000,"width":1000,"alignSelf":"AlignFlexEnd"}}}},"align_self_flex_start":{"style":{"width":10000,"height":10000},"children":{"child0":{"style":{"height":1000,"width":1000,"alignSelf":"AlignFlexStart"}}}},"align_self_flex_end_override_flex_start":{"style":{"width":10000,"height":10000,"alignItems":"AlignFlexStart"},"children":{"child0":{"style":{"height":1000,"width":1000,"alignSelf":"AlignFlexEnd"}}}},"border_no_size":{"style":{"border":1000}},"border_container_match_child":{"style":{"border":1000},"children":{"child0":{"style":{"width":1000,"height":1000}}}},"border_stretch_child":{"style":{"width":10000,"height":10000,"border":1000},"children":{"child0":{"style":{"height":1000}}}},"border_center_child":{"style":{"width":10000,"height":10000,"borderTop":1000,"borderBottom":2000,"alignItems":"AlignCenter","justifyContent":"JustifyCenter"},"children":{"child0":{"style":{"height":1000,"width":1000}}}},"max_width":{"style":{"width":10000,"height":10000},"children":{"child0":{"style":{"height":1000,"maxWidth":5000}}}},"max_height":{"style":{"width":10000,"height":10000,"flexDirection":"Row"},"children":{"child0":{"style":{"width":1000,"maxHeight":5000}}}},"padding_no_size":{"style":{"padding":1000}},"padding_container_match_child":{"style":{"padding":1000},"children":{"child0":{"style":{"width":1000,"height":1000}}}},"padding_stretch_child":{"style":{"width":10000,"height":10000,"padding":1000},"children":{"child0":{"style":{"height":1000}}}},"padding_center_child":{"style":{"width":10000,"height":10000,"paddingTop":1000,"paddingBottom":2000,"alignItems":"AlignCenter","justifyContent":"JustifyCenter"},"children":{"child0":{"style":{"height":1000,"width":1000}}}},"absolute_layout_width_height_start_top":{"style":{"width":10000,"height":10000},"children":{"child0":{"style":{"width":1000,"height":1000,"positionType":"Absolute","top":1000}}}},"absolute_layout_width_height_end_bottom":{"style":{"width":10000,"height":10000},"children":{"child0":{"style":{"width":1000,"height":1000,"positionType":"Absolute","bottom":1000}}}},"absolute_layout_start_top_end_bottom":{"style":{"width":10000,"height":10000},"children":{"child0":{"style":{"positionType":"Absolute","top":1000,"bottom":1000}}}},"absolute_layout_width_height_start_top_end_bottom":{"style":{"width":10000,"height":10000},"children":{"child0":{"style":{"width":1000,"height":1000,"positionType":"Absolute","top":1000,"bottom":1000}}}},"do_not_clamp_height_of_absolute_node_to_height_of_its_overflow_hidden_parent":{"style":{"height":5000,"width":5000,"overflow":"Hidden","flexDirection":"Row"},"children":{"child0":{"style":{"positionType":"Absolute","top":0},"children":{"child0":{"style":{"width":10000,"height":10000}}}}}},"flex_direction_column_no_height":{"style":{"width":10000},"children":{"child0":{"style":{"height":1000}},"child1":{"style":{"height":1000}},"child2":{"style":{"height":1000}}}},"flex_direction_row_no_width":{"style":{"height":10000,"flexDirection":"Row"},"children":{"child0":{"style":{"width":1000}},"child1":{"style":{"width":1000}},"child2":{"style":{"width":1000}}}},"flex_direction_column":{"style":{"height":10000,"width":10000},"children":{"child0":{"style":{"height":1000}},"child1":{"style":{"height":1000}},"child2":{"style":{"height":1000}}}},"flex_direction_row":{"style":{"height":10000,"width":10000,"flexDirection":"Row"},"children":{"child0":{"style":{"width":1000}},"child1":{"style":{"width":1000}},"child2":{"style":{"width":1000}}}},"flex_direction_column_reverse":{"style":{"height":10000,"width":10000,"flexDirection":"ColumnReverse"},"children":{"child0":{"style":{"height":1000}},"child1":{"style":{"height":1000}},"child2":{"style":{"height":1000}}}},"flex_direction_row_reverse":{"style":{"height":10000,"width":10000,"flexDirection":"RowReverse"},"children":{"child0":{"style":{"width":1000}},"child1":{"style":{"width":1000}},"child2":{"style":{"width":1000}}}},"wrap_column":{"style":{"height":10000,"width":6000,"flexWrap":"CssWrap"},"children":{"child0":{"style":{"height":3000,"width":3000}},"child1":{"style":{"height":3000,"width":3000}},"child2":{"style":{"height":3000,"width":3000}},"child3":{"style":{"height":3000,"width":3000}}}},"wrap_row":{"style":{"width":10000,"flexDirection":"Row","flexWrap":"CssWrap"},"children":{"child0":{"style":{"height":3000,"width":3000}},"child1":{"style":{"height":3000,"width":3000}},"child2":{"style":{"height":3000,"width":3000}},"child3":{"style":{"height":3000,"width":3000}}}},"wrap_row_align_items_flex_end":{"style":{"width":10000,"flexDirection":"Row","flexWrap":"CssWrap","alignItems":"AlignFlexEnd"},"children":{"child0":{"style":{"height":1000,"width":3000}},"child1":{"style":{"height":2000,"width":3000}},"child2":{"style":{"height":3000,"width":3000}},"child3":{"style":{"height":3000,"width":3000}}}},"wrap_row_align_items_center":{"style":{"width":10000,"flexDirection":"Row","flexWrap":"CssWrap","alignItems":"AlignCenter"},"children":{"child0":{"style":{"height":1000,"width":3000}},"child1":{"style":{"height":2000,"width":3000}},"child2":{"style":{"height":3000,"width":3000}},"child3":{"style":{"height":3000,"width":3000}}}},"margin_start":{"style":{"width":10000,"height":10000,"flexDirection":"Row"},"children":{"child0":{"style":{"width":1000}}}},"margin_end":{"style":{"width":10000,"height":10000,"flexDirection":"Row","justifyContent":"JustifyFlexEnd"},"children":{"child0":{"style":{"width":1000}}}},"margin_left":{"style":{"width":10000,"height":10000,"flexDirection":"Row"},"children":{"child0":{"style":{"width":1000,"marginLeft":1000}}}},"margin_top":{"style":{"width":10000,"height":10000},"children":{"child0":{"style":{"height":1000,"marginTop":1000}}}},"margin_right":{"style":{"width":10000,"height":10000,"flexDirection":"Row","justifyContent":"JustifyFlexEnd"},"children":{"child0":{"style":{"width":1000,"marginRight":1000}}}},"margin_bottom":{"style":{"width":10000,"height":10000,"justifyContent":"JustifyFlexEnd"},"children":{"child0":{"style":{"height":1000,"marginBottom":1000}}}},"align_content_flex_start":{"style":{"width":10000,"height":10000,"flexWrap":"CssWrap","flexDirection":"Column","alignContent":"AlignFlexStart"},"children":{"child0":{"style":{"width":5000,"height":1000}},"child1":{"style":{"width":5000,"height":1000}},"child2":{"style":{"width":5000,"height":1000}},"child3":{"style":{"width":5000,"height":1000}},"child4":{"style":{"width":5000,"height":1000}}}},"align_content_flex_end":{"style":{"width":10000,"height":10000,"flexWrap":"CssWrap","flexDirection":"Column","alignContent":"AlignFlexEnd"},"children":{"child0":{"style":{"width":5000,"height":1000}},"child1":{"style":{"width":5000,"height":1000}},"child2":{"style":{"width":5000,"height":1000}},"child3":{"style":{"width":5000,"height":1000}},"child4":{"style":{"width":5000,"height":1000}}}},"align_content_center":{"style":{"width":10000,"height":10000,"flexWrap":"CssWrap","flexDirection":"Column","alignContent":"AlignCenter"},"children":{"child0":{"style":{"width":5000,"height":1000}},"child1":{"style":{"width":5000,"height":1000}},"child2":{"style":{"width":5000,"height":1000}},"child3":{"style":{"width":5000,"height":1000}},"child4":{"style":{"width":5000,"height":1000}}}},"align_content_stretch":{"style":{"width":10000,"height":10000,"flexWrap":"CssWrap","flexDirection":"Column","alignContent":"AlignStretch"},"children":{"child0":{"style":{"width":5000}},"child1":{"style":{"width":5000}},"child2":{"style":{"width":5000}},"child3":{"style":{"width":5000}},"child4":{"style":{"width":5000}}}},"justify_content_row_flex_start":{"style":{"width":10200,"height":10200,"flexDirection":"Row","justifyContent":"JustifyFlexStart"},"children":{"child0":{"style":{"width":1000}},"child1":{"style":{"width":1000}},"child2":{"style":{"width":1000}}}},"justify_content_row_flex_end":{"style":{"width":10200,"height":10200,"flexDirection":"Row","justifyContent":"JustifyFlexEnd"},"children":{"child0":{"style":{"width":1000}},"child1":{"style":{"width":1000}},"child2":{"style":{"width":1000}}}},"justify_content_row_center":{"style":{"width":10200,"height":10200,"flexDirection":"Row","justifyContent":"JustifyCenter"},"children":{"child0":{"style":{"width":1000}},"child1":{"style":{"width":1000}},"child2":{"style":{"width":1000}}}},"justify_content_row_space_between":{"style":{"width":10200,"height":10200,"flexDirection":"Row","justifyContent":"JustifySpaceBetween"},"children":{"child0":{"style":{"width":1000}},"child1":{"style":{"width":1000}},"child2":{"style":{"width":1000}}}},"justify_content_row_space_around":{"style":{"width":10200,"height":10200,"flexDirection":"Row","justifyContent":"JustifySpaceAround"},"children":{"child0":{"style":{"width":1000}},"child1":{"style":{"width":1000}},"child2":{"style":{"width":1000}}}},"justify_content_column_flex_start":{"style":{"width":10200,"height":10200,"justifyContent":"JustifyFlexStart"},"children":{"child0":{"style":{"height":1000}},"child1":{"style":{"height":1000}},"child2":{"style":{"height":1000}}}},"justify_content_column_flex_end":{"style":{"width":10200,"height":10200,"justifyContent":"JustifyFlexEnd"},"children":{"child0":{"style":{"height":1000}},"child1":{"style":{"height":1000}},"child2":{"style":{"height":1000}}}},"justify_content_column_center":{"style":{"width":10200,"height":10200,"justifyContent":"JustifyCenter"},"children":{"child0":{"style":{"height":1000}},"child1":{"style":{"height":1000}},"child2":{"style":{"height":1000}}}},"justify_content_column_space_between":{"style":{"width":10200,"height":10200,"justifyContent":"JustifySpaceBetween"},"children":{"child0":{"style":{"height":1000}},"child1":{"style":{"height":1000}},"child2":{"style":{"height":1000}}}},"justify_content_column_space_around":{"style":{"width":10200,"height":10200,"justifyContent":"JustifySpaceAround"},"children":{"child0":{"style":{"height":1000}},"child1":{"style":{"height":1000}},"child2":{"style":{"height":1000}}}},"border_flex_child":{"style":{"width":10000,"height":10000,"border":1000},"children":{"child0":{"style":{"width":1000,"flexGrow":"1"}}}},"min_height":{"style":{"width":10000,"height":10000},"children":{"child0":{"style":{"flexGrow":"1","minHeight":6000}},"child1":{"style":{"flexGrow":"1"}}}},"min_width":{"style":{"width":10000,"height":10000,"flexDirection":"Row"},"children":{"child0":{"style":{"flexGrow":"1","minWidth":6000}},"child1":{"style":{"flexGrow":"1"}}}},"padding_flex_child":{"style":{"width":10000,"height":10000,"padding":1000},"children":{"child0":{"style":{"width":1000,"flexGrow":"1"}}}},"margin_and_flex_row":{"style":{"width":10000,"height":10000,"flexDirection":"Row"},"children":{"child0":{"style":{"flexGrow":"1"}}}},"margin_and_flex_column":{"style":{"width":10000,"height":10000},"children":{"child0":{"style":{"marginTop":1000,"marginBottom":1000,"flexGrow":"1"}}}},"margin_and_stretch_row":{"style":{"width":10000,"height":10000,"flexDirection":"Row"},"children":{"child0":{"style":{"marginTop":1000,"marginBottom":1000,"flexGrow":"1"}}}},"margin_and_stretch_column":{"style":{"width":10000,"height":10000},"children":{"child0":{"style":{"flexGrow":"1"}}}},"margin_with_sibling_row":{"style":{"width":10000,"height":10000,"flexDirection":"Row"},"children":{"child0":{"style":{"flexGrow":"1"}},"child1":{"style":{"flexGrow":"1"}}}},"margin_with_sibling_column":{"style":{"width":10000,"height":10000},"children":{"child0":{"style":{"marginBottom":1000,"flexGrow":"1"}},"child1":{"style":{"flexGrow":"1"}}}},"flex_basis_flex_grow_column":{"style":{"width":10000,"height":10000},"children":{"child0":{"style":{"flexBasis":"50px","flexGrow":"1"}},"child1":{"style":{"flexGrow":"1"}}}},"flex_basis_flex_grow_row":{"style":{"width":10000,"height":10000,"flexDirection":"Row"},"children":{"child0":{"style":{"flexBasis":"50px","flexGrow":"1"}},"child1":{"style":{"flexGrow":"1"}}}},"flex_basis_flex_shrink_column":{"style":{"width":10000,"height":10000},"children":{"child0":{"style":{"flexBasis":"100px","flexShrink":"1"}},"child1":{"style":{"flexBasis":"50px"}}}},"flex_basis_flex_shrink_row":{"style":{"width":10000,"height":10000,"flexDirection":"Row"},"children":{"child0":{"style":{"flexBasis":"100px","flexShrink":"1"}},"child1":{"style":{"flexBasis":"50px"}}}},"flex_basis_flex_grow_undefined_main":{"style":{"width":10000},"children":{"child0":{"style":{"flexBasis":"100px","flexGrow":"1"}},"child1":{"style":{"flexBasis":"50px"}}}},"jwalke_border_width_only_start":{"style":{"width":10000,"height":10000,"borderTop":1000,"borderBottom":2000,"alignItems":"AlignCenter","justifyContent":"JustifyCenter"},"children":{"child0":{"style":{"height":1000,"width":1000}}}},"jwalke_border_width_only_end":{"style":{"width":10000,"height":10000,"borderTop":1000,"borderBottom":2000,"alignItems":"AlignCenter","justifyContent":"JustifyCenter"},"children":{"child0":{"style":{"height":1000,"width":1000}}}},"start_overrides_margin":{"style":{"width":10000,"height":10000},"children":{"child0":{"style":{"marginLeft":2000,"marginRight":2000,"flexGrow":"1"}}}},"end_overrides_margin":{"style":{"width":10000,"height":10000},"children":{"child0":{"style":{"marginLeft":2000,"marginRight":2000,"flexGrow":"1"}}}},"start_overrides_padding":{"style":{"width":10000,"height":10000},"children":{"child0":{"style":{"paddingLeft":2000,"paddingRight":2000,"flexGrow":"1"}}}},"end_overrides_padding":{"style":{"width":10000,"height":10000},"children":{"child0":{"style":{"paddingLeft":2000,"paddingRight":2000,"flexGrow":"1"}}}},"start_overrides_border":{"style":{"width":10000,"height":10000},"children":{"child0":{"style":{"borderLeft":2000,"borderRight":2000,"flexGrow":"1"}}}},"end_overrides_border":{"style":{"width":10000,"height":10000},"children":{"child0":{"style":{"borderLeft":2000,"borderRight":2000,"flexGrow":"1"}}}},"start_overrides":{"style":{"width":10000,"height":10000},"children":{"child0":{"style":{"positionType":"Absolute","left":2000,"right":2000,"flexGrow":"1"}}}},"end_overrides":{"style":{"width":10000,"height":10000},"children":{"child0":{"style":{"positionType":"Absolute","left":2000,"right":2000,"flexGrow":"1"}}}}};
/**
* Used to render test data to markup for the purpose of measuring layout.
*/
var styleTestDataToMarkupMap = {
'positionType': (key, val, isLtr) => ({key: 'position', val: positionTypeMarkupValue(val)}),
'direction': (key, val, isLtr) => ({key: 'direction', val: directionMarkupValue(val)}),
'flexDirection': (key, val, isLtr) => ({key: 'flex-direction', val: flexDirectionMarkupValue(val)}),
'justifyContent': (key, val, isLtr) => ({key: 'justify-content', val: justifyMarkupValue(val)}),
'alignContent': (key, val, isLtr) => ({key: 'align-content', val: alignMarkupValue(val)}),
'alignItems': (key, val, isLtr) => ({key: 'align-items', val: alignMarkupValue(val)}),
'alignSelf': (key, val, isLtr) => ({key: 'align-self', val: alignMarkupValue(val)}),
'overflow': (key, val, isLtr) => ({key: 'overflow', val: overflowMarkupValue(val)}),
'flexWrap': (key, val, isLtr) => ({key: 'flex-wrap', val: wrapMarkupValue(val)}),
'flexGrow': (key, val, isLtr) => ({key: 'flex-grow', val: val}),
'flexShrink': (key, val, isLtr) => ({key: 'flex-shrink', val: val}),
'flexBasis': (key, val, isLtr) => ({key: 'flex-basis', val: pixelMarkupValue(val)}),
// Position.
// Not sure `position` is even a real css property (It represents "all").
'position': (key, val, isLtr) => ({key: 'position', val: pixelMarkupValue(val)}),
'top': (key, val, isLtr) => ({key: 'top', val: pixelMarkupValue(val)}),
'bottom': (key, val, isLtr) => ({key: 'bottom', val: pixelMarkupValue(val)}),
'left': (key, val, isLtr) => ({key: 'left', val: pixelMarkupValue(val)}),
'right': (key, val, isLtr) => ({key: 'right', val: pixelMarkupValue(val)}),
'start': (key, val, isLtr) => ({key: startFor(isLtr), val: pixelMarkupValue(val)}),
'endd': (key, val, isLtr) => ({key: endFor(isLtr), val: pixelMarkupValue(val)}),
'vertical': (key, val, isLtr) => ({key: 'vertical', val: pixelMarkupValue(val)}),
'horizontal': (key, val, isLtr) => ({key: 'horizontal', val: pixelMarkupValue(val)}),
// Margin.
'margin': (key, val, isLtr) => ({key: 'margin', val: pixelMarkupValue(val)}),
'marginTop': (key, val, isLtr) => ({key: 'margin-top', val: pixelMarkupValue(val)}),
'marginBottom': (key, val, isLtr) => ({key: 'margin-bottom', val: pixelMarkupValue(val)}),
'marginLeft': (key, val, isLtr) => ({key: 'margin-left', val: pixelMarkupValue(val)}),
'marginRight': (key, val, isLtr) => ({key: 'margin-right', val: pixelMarkupValue(val)}),
'marginStart': (key, val, isLtr) => ({key: 'margin-' + startFor(isLtr), val: pixelMarkupValue(val)}),
'marginEnd': (key, val, isLtr) => ({key: 'margin-' + endFor(isLtr), val: pixelMarkupValue(val)}),
'marginVertical': (key, val, isLtr) => ({key: 'margin-vertical', val: pixelMarkupValue(val)}),
'marginHorizontal': (key, val, isLtr) => ({key: 'margin-horizontal', val: pixelMarkupValue(val)}),
// Padding.
'padding': (key, val, isLtr) => ({key: 'padding', val: pixelMarkupValue(val)}),
'paddingTop': (key, val, isLtr) => ({key: 'padding-top', val: pixelMarkupValue(val)}),
'paddingBottom': (key, val, isLtr) => ({key: 'padding-bottom', val: pixelMarkupValue(val)}),
'paddingLeft': (key, val, isLtr) => ({key: 'padding-left', val: pixelMarkupValue(val)}),
'paddingRight': (key, val, isLtr) => ({key: 'padding-right', val: pixelMarkupValue(val)}),
'paddingStart': (key, val, isLtr) => ({key: 'padding-' + startFor(isLtr), val: pixelMarkupValue(val)}),
'paddingEnd': (key, val, isLtr) => ({key: 'padding-' + endFor(isLtr), val: pixelMarkupValue(val)}),
'paddingHorizontal': (key, val, isLtr) => ({key: 'padding-horizontal', val: pixelMarkupValue(val)}),
'paddingVertical': (key, val, isLtr) => ({key: 'padding-vertical', val: pixelMarkupValue(val)}),
// Border.
'border': (key, val, isLtr) => ({key: 'border', val: pixelMarkupValue(val)}),
'borderTop': (key, val, isLtr) => ({key: 'border-top-width', val: pixelMarkupValue(val)}),
'borderBottom': (key, val, isLtr) => ({key: 'border-bottom-width', val: pixelMarkupValue(val)}),
'borderLeft': (key, val, isLtr) => ({key: 'border-left-width', val: pixelMarkupValue(val)}),
'borderRight': (key, val, isLtr) => ({key: 'border-right-width', val: pixelMarkupValue(val)}),
'borderStart': (key, val, isLtr) => ({key: 'border-' + startFor(isLtr) + '-width', val: pixelMarkupValue(val)}),
'borderEnd': (key, val, isLtr) => ({key: 'border-' + endFor(isLtr) + '-width', val: pixelMarkupValue(val)}),
'borderHorizontal': (key, val, isLtr) => ({key: 'border-horizontal-width', val: pixelMarkupValue(val)}),
'borderVertical': (key, val, isLtr) => ({key: 'border-vertical-width', val: pixelMarkupValue(val)}),
// Dimensions.
'width': (key, val, isLtr) => ({key: 'width', val: pixelMarkupValue(val)}),
'height': (key, val, isLtr) => ({key: 'height', val: pixelMarkupValue(val)}),
'minWidth': (key, val, isLtr) => ({key: 'min-width', val: pixelMarkupValue(val)}),
'maxWidth': (key, val, isLtr) => ({key: 'max-width', val: pixelMarkupValue(val)}),
'minHeight': (key, val, isLtr) => ({key: 'min-height', val: pixelMarkupValue(val)}),
'maxHeight': (key, val, isLtr) => ({key: 'max-height', val: pixelMarkupValue(val)}),
};
let capitalize = (s) => {
return s.charAt(0).toUppercase() + s.substr(1);
};
/**
* This converts the other direction - from markup, to style test data. This
* is only even used to convert html snippets into test data, which is then
* converted *back* into HTML that is actually measured. This is only needed
* when adding new test cases.
*/
var markupToStyleTestDatapMap = {
'position': (key, val, useFloats) => ({key: 'positionType', val: positionTypeValue(val)}),
'direction': (key, val, useFloats) => ({key: 'direction', val: directionValue(val)}),
'flex-direction': (key, val, useFloats) => ({key: 'flexDirection', val: flexDirectionValue(val)}),
'justify-content': (key, val, useFloats) => ({key: 'justifyContent', val: justifyValue(val)}),
'align-content': (key, val, useFloats) => ({key: 'alignContent', val: alignValue(val)}),
'align-items': (key, val, useFloats) => ({key: 'alignItems', val: alignValue(val)}),
'align-self': (key, val, useFloats) => ({key: 'alignSelf', val: alignValue(val)}),
'overflow': (key, val, useFloats) => ({key: 'overflow', val: overflowValue(val)}),
'flex-wrap': (key, val, useFloats) => ({key: 'flexWrap', val: wrapValue(val)}),
'flex-grow': (key, val, useFloats) => ({key: 'flexGrow', val: val}),
'flex-shrink': (key, val, useFloats) => ({key: 'flexShrink', val: val}),
'flex-basis': (key, val, useFloats) => ({key: 'flexBasis', val: markupPixelValueToIntegerEncoding(val)}),
// Position.
// Not sure `position` is even a real css property (It represents "all").
//'position': (key, val, useFloats) => ({key: 'position', val: markupPixelValueToIntegerEncoding(val)}),
'top': (key, val, useFloats) => ({key: 'top', val: markupPixelValueToIntegerEncoding(val)}),
'bottom': (key, val, useFloats) => ({key: 'bottom', val: markupPixelValueToIntegerEncoding(val)}),
'left': (key, val, useFloats) => ({key: 'left', val: markupPixelValueToIntegerEncoding(val)}),
'right': (key, val, useFloats) => ({key: 'right', val: markupPixelValueToIntegerEncoding(val)}),
'start': (key, val, useFloats) => ({key: 'start', val: markupPixelValueToIntegerEncoding(val)}),
'end': (key, val, useFloats) => ({key: 'endd', val: markupPixelValueToIntegerEncoding(val)}),
'vertical': (key, val, useFloats) => ({key: 'vertical', val: markupPixelValueToIntegerEncoding(val)}),
'horizontal': (key, val, useFloats) => ({key: 'horizontal', val: markupPixelValueToIntegerEncoding(val)}),
// Margin.
'margin': (key, val, useFloats) => ({key: 'margin', val: markupPixelValueToIntegerEncoding(val)}),
'margin-top': (key, val, useFloats) => ({key: 'marginTop', val: markupPixelValueToIntegerEncoding(val)}),
'margin-bottom': (key, val, useFloats) => ({key: 'marginBottom', val: markupPixelValueToIntegerEncoding(val)}),
'margin-left': (key, val, useFloats) => ({key: 'marginLeft', val: markupPixelValueToIntegerEncoding(val)}),
'margin-right': (key, val, useFloats) => ({key: 'marginRight', val: markupPixelValueToIntegerEncoding(val)}),
'margin-start': (key, val, useFloats) => ({key: 'marginStart', val: markupPixelValueToIntegerEncoding(val)}),
'margin-end': (key, val, useFloats) => ({key: 'marginEnd', val: markupPixelValueToIntegerEncoding(val)}),
'margin-vertical': (key, val, useFloats) => ({key: 'marginVertical', val: markupPixelValueToIntegerEncoding(val)}),
'margin-horizontal': (key, val, useFloats) => ({key: 'marginHorizontal', val: markupPixelValueToIntegerEncoding(val)}),
// Padding.
'padding': (key, val, useFloats) => ({key: 'padding', val: markupPixelValueToIntegerEncoding(val)}),
'padding-top': (key, val, useFloats) => ({key: 'paddingTop', val: markupPixelValueToIntegerEncoding(val)}),
'padding-bottom': (key, val, useFloats) => ({key: 'paddingBottom', val: markupPixelValueToIntegerEncoding(val)}),
'padding-left': (key, val, useFloats) => ({key: 'paddingLeft', val: markupPixelValueToIntegerEncoding(val)}),
'padding-right': (key, val, useFloats) => ({key: 'paddingRight', val: markupPixelValueToIntegerEncoding(val)}),
'padding-start': (key, val, useFloats) => ({key: 'paddingStart', val: markupPixelValueToIntegerEncoding(val)}),
'padding-end': (key, val, useFloats) => ({key: 'paddingEnd', val: markupPixelValueToIntegerEncoding(val)}),
'padding-horizontal': (key, val, useFloats) => ({key: 'paddingHorizontal', val: markupPixelValueToIntegerEncoding(val)}),
'padding-vertical': (key, val, useFloats) => ({key: 'paddingVertical', val: markupPixelValueToIntegerEncoding(val)}),
// Border.
'border-width': (key, val, useFloats) => ({key: 'border', val: markupPixelValueToIntegerEncoding(val)}),
'border-top-width': (key, val, useFloats) => ({key: 'borderTop', val: markupPixelValueToIntegerEncoding(val)}),
'border-bottom-width': (key, val, useFloats) => ({key: 'borderBottom', val: markupPixelValueToIntegerEncoding(val)}),
'border-left-width': (key, val, useFloats) => ({key: 'borderLeft', val: markupPixelValueToIntegerEncoding(val)}),
'border-right-width': (key, val, useFloats) => ({key: 'borderRight', val: markupPixelValueToIntegerEncoding(val)}),
'border-start-width': (key, val, useFloats) => ({key: 'borderStart', val: markupPixelValueToIntegerEncoding(val)}),
'border-end-width': (key, val, useFloats) => ({key: 'borderEnd', val: markupPixelValueToIntegerEncoding(val)}),
'border-horizontal-width': (key, val, useFloats) => ({key: 'borderHorizontal', val: markupPixelValueToIntegerEncoding(val)}),
'border-vertical-width': (key, val, useFloats) => ({key: 'borderVertical', val: markupPixelValueToIntegerEncoding(val)}),
// Dimensions.
'width': (key, val, useFloats) => ({key: 'width', val: markupPixelValueToIntegerEncoding(val)}),
'height': (key, val, useFloats) => ({key: 'height', val: markupPixelValueToIntegerEncoding(val)}),
'min-width': (key, val, useFloats) => ({key: 'minWidth', val: markupPixelValueToIntegerEncoding(val)}),
'max-width': (key, val, useFloats) => ({key: 'maxWidth', val: markupPixelValueToIntegerEncoding(val)}),
'min-height': (key, val, useFloats) => ({key: 'minHeight', val: markupPixelValueToIntegerEncoding(val)}),
'max-height': (key, val, useFloats) => ({key: 'maxHeight', val: markupPixelValueToIntegerEncoding(val)}),
};
/**
* While we don't yet support some expanded properties (such as
* border-vertical-width = border-left=width + border-right-width), we will map
* them to all the individual properties for now.
*/
var expandedEquivalentStyleKeys = {
'position': ['top', 'bottom', 'left', 'right'],
'vertical': ['top', 'bottom'],
'horizontal': ['left', 'right'],
// Margin.
'margin': ['marginTop', 'marginBottom', 'marginLeft', 'marginRight'],
'margin-vertical': ['marginTop', 'marginBottom'],
'margin-horizontal': ['marginLeft', 'marginRight'],
// Padding.
'padding': ['paddingTop', 'paddingBottom', 'paddingLeft', 'paddingRight'],
'padding-vertical': ['paddingTop', 'paddingBottom'],
'padding-horizontal': ['paddingLeft', 'paddingRight'],
// Border.
'border': ['borderTop', 'borderBottom', 'borderLeft', 'borderRight'],
'border-vertical': ['borderTop', 'borderBottom'],
'border-horizontal': ['borderLeft', 'borderRight'],
};
var computeStyleStringForTestDataItem = (testDataItem, isLtr) => {
var styleString = 'style="';
for (var styleKey in testDataItem.style) {
// Skip over start/endd because we want to make sure they appear last.
if (styleKey !== 'start' && styleKey !== 'endd') {
if (!styleTestDataToMarkupMap[styleKey]) {
throw new Error("Encountered unsupported style key " + styleKey + ". Styles should be in terms of ReLayout styles.");
}
var styleKeyVal = styleTestDataToMarkupMap[styleKey](styleKey, testDataItem.style[styleKey], isLtr);
styleString += styleKeyVal.key + ':' + styleKeyVal.val + '; ';
}
}
if (testDataItem.style['start']) {
let styleKeyVal = styleTestDataToMarkupMap['start']('start', testDataItem.style['start'], isLtr);
styleString += styleKeyVal.key + ':' + styleKeyVal.val + '; ';
}
if (testDataItem.style['endd']) {
let styleKeyVal = styleTestDataToMarkupMap['endd']('endd', testDataItem.style['endd'], isLtr);
styleString += styleKeyVal.key + ':' + styleKeyVal.val + '; ';
}
styleString += '"';
return styleString;
};
let legacyDomToJson = function(container) {
if (!container) {
return null;
}
let ret = {};
var styleAttr = container.getAttribute('style');
var styleItms = !styleAttr ? [] : styleAttr.split(';').filter(s => (s.trim() !== '')).map(seg => {
let kv = seg.split(':');
let key = kv[0].trim();
let val = kv[1].trim();
if (!markupToStyleTestDatapMap[key]) {
return null;
}
let convertedKv = markupToStyleTestDatapMap[key](key, val, false);
return {key: convertedKv.key, val: convertedKv.val};
}).filter(x => !!x);
let style = {};
for (var i = 0; i < styleItms.length; i++) {
let styleItm = styleItms[i];
let styleItmKey = styleItm.key;
if (expandedEquivalentStyleKeys[styleItmKey]) {
let expandedKeys = expandedEquivalentStyleKeys[styleItmKey]
for (var i = 0; i < expandedKeys.length; i++) {
let expandedKey = expandedKeys[i];
style[expandedKey] = styleItm.val;
}
} else {
style[styleItm.key] = styleItm.val;
}
}
ret.style = style;
if (container.children.length) {
let children = {};
for (var i = 0; i < container.children.length; i++) {
var domChild = container.children[i];
children[domChild.id || 'child' + i] = legacyDomToJson(domChild);
}
ret.children = children;
}
return ret;
};
window.legacyMarkupToJson = function(markup) {
let container = document.createElement('div');
container.innerHTML = markup;
return legacyDomToJson(container, false).children;
};
let forEachTestData = (testData, computedKeyPathSoFar, cb) => {
for (var testKey in testData) {
let totalKeyPath = computedKeyPathSoFar + '_' + testKey;
let testDataItem = testData[testKey];
cb(testData[testKey], testKey, totalKeyPath);
}
};
var startFor = (isLtr) => isLtr ? 'left' : 'right';
var endFor = (isLtr) => isLtr ? 'right' : 'left';
function overflowValue(value) {
switch (value) {
case 'visible': return 'Visible';
case 'hidden': return 'Hidden';
}
}
function wrapValue(value) {
switch (value) {
case 'wrap': return 'CssWrap';
case 'nowrap': return 'CssNoWrap';
}
}
function flexDirectionValue(value) {
switch (value) {
case 'row': return 'Row';
case 'row-reverse': return 'RowReverse';
case 'column': return 'Column';
case 'column-reverse': return 'ColumnReverse';
}
}
function justifyValue(value) {
switch (value) {
case 'center': return 'JustifyCenter';
case 'space-around': return 'JustifySpaceAround';
case 'space-between': return 'JustifySpaceBetween';
case 'flex-start': return 'JustifyFlexStart';
case 'flex-end': return 'JustifyFlexEnd';
}
}
function positionTypeValue(value) {
switch (value) {
case 'absolute': return 'Absolute';
default: return 'Relative'
}
}
function directionValue(value) {
switch (value) {
case 'ltr': return 'Ltr';
case 'rtl': return 'Rtl';
case 'inherit': return 'Inherit';
}
}
function alignValue(value) {
switch (value) {
case 'auto': return 'AlignAuto';
case 'center': return 'AlignCenter';
case 'stretch': return 'AlignStretch';
case 'flex-start': return 'AlignFlexStart';
case 'flex-end': return 'AlignFlexEnd';
}
}
function markupPixelValueToIntegerEncoding(value) {
switch (value) {
case 'auto': return 'cssUndefined';
case 'undefined': return 'cssUndefined';
default:
let ret = Math.trunc(((+(value.replace('px', ''))) * unitsPerPixel));
return ret;
}
}
/**
* Used to turn test data into the actual test cases.
*
*/
var styleTestDataToEncodingMap = {
/**
* @param {bool} useFloats Whether or not to encode data in floats vs. fixed
* point.
*/
'flexGrow': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'flexShrink': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'flexBasis': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
// Position.
// Not sure `position` is even a real css property (It represents "all").
'position': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'top': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'bottom': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'left': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'right': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'start': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'endd': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'vertical': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'horizontal': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
// Margin.
'margin': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'marginTop': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'marginBottom': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'marginLeft': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'marginRight': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'marginStart': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'marginEnd': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'marginVertical': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'marginHorizontal': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
// Padding.
'padding': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'paddingTop': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'paddingBottom': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'paddingLeft': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'paddingRight': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'paddingStart': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'paddingEnd': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'paddingHorizontal': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'paddingVertical': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
// Border.
'border': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'borderTop': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'borderBottom': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'borderLeft': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'borderRight': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'borderStart': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'borderEnd': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'borderHorizontal': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'borderVertical': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
// Dimensions.
'width': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'height': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'minWidth': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'maxWidth': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'minHeight': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val)),
'maxHeight': (val, useFloats) => ((useFloats ? testDataToFloatEncoding : testDataToIntEncoding)(val))
};
window.generateMarkup = (testData, computedKeyPathSoFar, isLtr) => {
var res = "";
forEachTestData(testData, computedKeyPathSoFar, (testDataItem, testKey, totalKeyPath) => {
var idString = 'id="' + totalKeyPath + '" ';
var styleString = computeStyleStringForTestDataItem(testDataItem, isLtr);
let opn = "<div " + idString + styleString + (testDataItem.children ? ">\n " : "> </DIV>\n");
let childText = window.generateMarkup(testDataItem.children, totalKeyPath, isLtr);
let cls = testDataItem.children ? "\n</div>\n" : '';
res += opn + childText + cls;
});
return res;
};
window.onload = function() {
/**
* The buttons have event handlers that look for these values.
*/
document.body.children[0].innerHTML = (window.generateMarkup(window.testData, 'ltr', true));
document.body.children[1].innerHTML = (window.generateMarkup(window.testData, 'rtl', false));
window.fixedPointTest = window.printTest(window.testData, false, document.body.children[0], document.body.children[1]);
window.floatingPointTest = window.printTest(window.testData, true, document.body.children[0], document.body.children[1]);
document.getElementById('testDataViewer').innerHTML = JSON.stringify(window.testData);
}
window.printTest = function(testData, useFloats, LTRContainer, RTLContainer) {
testNum = 0;
var commentLines = [
'/*',
' * vim: set ft=rust:',
' * vim: set ft=reason:',
' */',
'/**',
' * Copyright (c) 2014-present, Facebook, Inc.',
' * All rights reserved.',
' *',
' * This source code is licensed under the BSD-style license found in the',
' * LICENSE file in the root directory of this source tree. An additional grant',
' * of patent rights can be found in the PATENTS file in the same directory.',
' */',
'',
];
commentLines.push('/**');
commentLines.push(' * @Generated by gentest/gentest.sh with the following input');
commentLines.push(' *');
var indentation = 0;
commentLines.push(JSON.stringify(testData));
commentLines.push(' *');
commentLines.push(' */');
commentLines.push('');
var ltrExpectedResults = getExpectedResults(testData, 'ltr');
var rtlExpectedResults = getExpectedResults(testData, 'rtl');
let testNameLines = [];
let testLines = [];
/**
* Lines containing function definitions, one for each benchmark.
*/
let benchmarkFunctionDefinitions = [];
/**
* List of core_bench benchmarks.
*/
let reasonListOfCoreBenchmarks = [
'let benchmarks = [];'
];
/**
* All the function bodies of the reasonListOfCoreBenchmarks functions in one
* list so the entire set may be tested as a single unit.
*/
let allBenchmarkLinesAsOne = [];
forEachTestData(testData, '', (testDataItem, testKey, totalKeyPath) => {
testNameLines.push('let ' + testKey + ' = "'+ testKey + '";');
let setupTreeStr = ' ' + setupTestTree(useFloats, testKey, testDataItem, 'root').join('\n');
let performLtrLine = ' Layout.layoutNode root cssUndefined cssUndefined Ltr;';
let performRtlLine = ' Layout.layoutNode root cssUndefined cssUndefined Rtl;';
testLines = testLines.concat([
'it ' + testKey + ' (fun () => {',
setupTreeStr,
performLtrLine,
'',
' ' + assertTestTree(useFloats, testDataItem, ltrExpectedResults[testKey], 'root', true).join('\n '),
'',
performRtlLine,
'',
' ' + assertTestTree(useFloats, testDataItem, rtlExpectedResults[testKey], 'root', true).join('\n '),
'});',
''
]);
let thisBenchmarkFunctionName = 'bench_' + testKey;
let thisBenchmarkFunction = [
' let ' + thisBenchmarkFunctionName + ' () => {',
' ' + setupTreeStr,
' ' + performLtrLine,
' ' + performRtlLine,
'};'
];
allBenchmarkLinesAsOne = allBenchmarkLinesAsOne.concat([
'/* ' + testKey + ' */',
setupTreeStr,
performLtrLine,
performRtlLine,
]);
benchmarkFunctionDefinitions = benchmarkFunctionDefinitions.concat (thisBenchmarkFunction);
reasonListOfCoreBenchmarks = reasonListOfCoreBenchmarks.concat([
'let benchmarks = LayoutTestUtils.shouldRun ' + testKey + ' ?',
' [',
' Bench.Test.create name::' + testKey,
' ' + thisBenchmarkFunctionName + ',',
' ...benchmarks',
' ] :',
' benchmarks;'
]);
});
testLines.push(' LayoutTestUtils.displayOutcomes ();');
reasonListOfCoreBenchmarks = reasonListOfCoreBenchmarks.map((line) => ' ' + line);
testLines = testLines.map((line) => ' ' + line);
let totalLines = [
'{commentLines}',
'open Flex;',
'let floatMult = ( *. );',
'let floatDiv = (/.);',
'let floatSub = (-.);',
'let module Node = {type context = unit; let nullContext = ();};',
'let module Encoding = ' + (useFloats ? 'FloatEncoding;' : 'FixedEncoding;'),
'let module LayoutTestUtils = LayoutTestUtils.Create Node Encoding;',
'let module Layout = Layout.Create Node Encoding;',
'module LayoutSupport = Layout.LayoutSupport;',
'open LayoutTestUtils;',
'open Encoding;',
'{testNameLines}',
'/**',
' * Since Core_bench is such a huge dependency and it doesn\'t compile with byte,',
' * we include a fake shim of it that we enable by default. To use the far',
' * superior Core_bench.',
' *',
' * - Comment out `include FakeCore;` below.',
' * - Uncomment `open Core_bench.Std;`',
' * - Delete the two targets in package.json (byteTarget, jsTarget)',
' * - Run `npm run build`, then `npm run bench`',
' *',
' */',
'let module FakeCore = {',
' let module Bench = {',
' let module Test = {',
' let create name::s itm => (s, itm);',
' };',
' let make_command listofCreatedBenchmarks => listofCreatedBenchmarks;',
' };',
' let module Core = {',
' let runCommand (name, func) => {',
' let numIterations = 10000;',
' let timesInMs = Array.create_float numIterations;',
' Gc.full_major ();',
' let startSeconds = Sys.time ();',
' for i in 0 to (numIterations - 1) {',
' let itemStartSeconds = Sys.time ();',
' func ();',
' let itemEndSeconds = Sys.time ();',
' timesInMs.(i) = floatSub itemEndSeconds itemStartSeconds',
' };',
' let endSeconds = Sys.time ();',
' print_string (',
' "Average ms for " ^',
' name ^',
' " " ^',
' string_of_float (',
' floatMult 1000.0 (floatDiv (floatSub endSeconds startSeconds) (float_of_int numIterations))',
' )',
' );',
' print_newline ();',
' Array.sort compare timesInMs;',
' print_string (',
' "Median ms for " ^ name ^ " " ^ string_of_float (floatMult 1000.0 timesInMs.(numIterations / 2)) ^ " (Not Valid For JS benchmarks)"',
' );',
' print_newline ()',
' };',
' let module Std = {',
' let module Command = {',
' let run listOftests => List.iter (fun command => runCommand command) listOftests;',
' };',
' };',
' };',
'};',
'',
'include FakeCore;',
'',
'/* open Core_bench.Std; */',
'',
'',
'',
'if (LayoutTestUtils.runMode === Bench) {',
' if LayoutTestUtils.shouldBenchmarkAllAsOne {',
' Core.Std.Command.run (Bench.make_command [Bench.Test.create name::"all-benchmarks" (fun()=>{',
' {allBenchmarkLinesAsOne}',
' })]);',
' } else {',
' {benchmarkFunctionDefinitions}',
' {reasonListOfCoreBenchmarks}',
' Core.Std.Command.run (Bench.make_command benchmarks);',
' }',
'} else {',
' {testLines}',
'};'
].join('\n')
.replace('{commentLines}', commentLines.join('\n'))
.replace('{testNameLines}', testNameLines.join('\n'))
.replace('{allBenchmarkLinesAsOne}', allBenchmarkLinesAsOne.join('\n '))
.replace('{benchmarkFunctionDefinitions}', benchmarkFunctionDefinitions.join('\n '))
.replace('{reasonListOfCoreBenchmarks}', reasonListOfCoreBenchmarks.join('\n '))
.replace('{testLines}', testLines.join('\n '));
return totalLines;
}
let testNum = 0;
let createLayoutExtensionNode = (useFloats, nodeName, top, left, width, height) => {
let converter = useFloats ? floatUnitsFromPixels : intUnitsFromPixels;
return (
'{...' +
nodeName +
'.layout, top:layoutTop, left: layoutLeft, width: layoutWidth, height: layoutHeight}'
).replace('layoutTop', converter(top))
.replace('layoutLeft', converter(left))
.replace('layoutWidth', converter(width))
.replace('layoutHeight', converter(height));
};
const createInequalityChecker = (useFloats, expectedResults, nodeName) => {
let expectedLayout = expectedResults.expectedLayout;
let converter = useFloats ? floatUnitsFromPixels : intUnitsFromPixels;
return nodeName + '.layout.top != ' + converter(expectedLayout.top) + ' || ' +
nodeName + '.layout.left != ' + converter(expectedLayout.left) + ' || ' +
nodeName + '.layout.width != ' + converter(expectedLayout.width) + ' || ' +
nodeName + '.layout.height != ' + converter(expectedLayout.height);
};
/**
* Should render container validation iff
* parentName is null || hasChildren (because it's nice to see the node
* validated again as a container this time).
*/
function assertTestTreePrint(useFloats, expectedResults, nodeBindingName, isRootmost) {
let shouldValidate = isRootmost || expectedResults.children != null;
if (!shouldValidate) {
return [].join('');
} else {
let childItems = [];
forEachTestData(expectedResults.children, nodeBindingName, (expectedItem, testKey, totalKeyPath) => {
let expectedLayout = expectedItem.expectedLayout;
childItems.push(
' (' +
createLayoutExtensionNode(useFloats, totalKeyPath, expectedLayout.top, expectedLayout.left, expectedLayout.width, expectedLayout.height) +
', ' +
totalKeyPath +
'.layout),'
);
});
let childLines = ['['].concat(childItems).concat([']']);
let expectedLayout = expectedResults.expectedLayout;
let assertionPrintingLines =
[
'assertLayouts testNum (expectedContainerLayout, observedContainerLayout)'
.replace('testNum', testNum++)
.replace(
'expectedContainerLayout',
createLayoutExtensionNode(useFloats, nodeBindingName, expectedLayout.top, expectedLayout.left, expectedLayout.width, expectedLayout.height)
)
.replace('observedContainerLayout', nodeBindingName + '.layout'),
].concat(childLines).concat([';']);
let recursePrettyPrintLines = [];
forEachTestData(expectedResults.children, nodeBindingName, (expectedItem, testKey, totalKeyPath) => {
recursePrettyPrintLines.push('');
recursePrettyPrintLines = recursePrettyPrintLines.concat(
assertTestTreePrint(useFloats, expectedItem, totalKeyPath, false)
);
});
let doThePrettyPrintingTestStr = assertionPrintingLines.concat(recursePrettyPrintLines);
return doThePrettyPrintingTestStr.join('\n');
}
};
function assertTestTreeFast(useFloats, testData, expectedResults, nodeBindingName) {
let ret = [
createInequalityChecker(useFloats, expectedResults, nodeBindingName)
];
forEachTestData(testData.children, nodeBindingName, (testDataItem, testKey, totalKeyPath) => {
ret.push(assertTestTreeFast(useFloats, testDataItem, expectedResults.children[testKey], totalKeyPath));
});
return ret.join(' ||\n');
};
/**
* @param {varType} testData Description
* @param {object} expectedResults Tree that mirrors the testData.
*/
function assertTestTree(useFloats, testData, expectedResults, nodeBindingName, isRootmost) {
let fastNumericCheckExprStr = assertTestTreeFast(useFloats, testData, expectedResults, nodeBindingName);
let testAndPrettyPrint = [
'if (' + fastNumericCheckExprStr + ') {',
' ' + assertTestTreePrint(useFloats, expectedResults, nodeBindingName, isRootmost),
'};'
];
return testAndPrettyPrint;
};
function setupTestTree(useFloats, testName, testData, letBindingNodeName) {
var lines = [];
var styleLines = [];
for (var reasonStyleKey in testData.style) {
let reasonStyleValue = testData.style[reasonStyleKey];
let value =
styleTestDataToEncodingMap[reasonStyleKey] ?
styleTestDataToEncodingMap[reasonStyleKey](reasonStyleValue, useFloats) :
reasonStyleValue;
styleLines.push(reasonStyleKey + ': ' + value);
}
if (styleLines.length > 0) {
lines = lines.concat([
'let ' + letBindingNodeName + '_style = {',
' ...LayoutSupport.defaultStyle,'
]);
lines = lines.concat(styleLines.map((sl) => ' ' + sl + ','));
lines.push('};');
} else {
lines = lines.concat([ 'let ' + letBindingNodeName + '_style = LayoutSupport.defaultStyle;']);
}
let childrenArray = [];
forEachTestData(testData.children, letBindingNodeName, (testDataItem, testKey, totalKeyPath) => {
lines.push('');
lines = lines.concat(setupTestTree(useFloats, testName + ' (child)', testDataItem, totalKeyPath));
childrenArray.push(totalKeyPath);
});
lines.push(
'let ' + letBindingNodeName + ' = LayoutSupport.createNode ' +
'withChildren::[|' + childrenArray.join(',') + '|] ' +
'andStyle::' + letBindingNodeName + '_style ();'
);
return lines;
}
function overflowMarkupValue(value) {
switch (value) {
case 'Visible': return 'visible';
case 'Hidden': return 'hidden';
}
}
function wrapMarkupValue(value) {
switch (value) {
case 'CssWrap': return 'wrap';
case 'CssNoWrap': return 'nowrap';
}
}
function flexDirectionMarkupValue(value) {
switch (value) {
case 'Row': return 'row';
case 'RowReverse': return 'row-reverse';
case 'Column': return 'column';
case 'ColumnReverse': return 'column-reverse';
}
}
function justifyMarkupValue(value) {
switch (value) {
case 'JustifyCenter': return 'center';
case 'JustifySpaceAround': return 'space-around';
case 'JustifySpaceBetween': return 'space-between';
case 'JustifyFlexStart': return 'flex-start';
case 'JustifyFlexEnd': return 'flex-end';
}
}
function positionTypeMarkupValue(value) {
switch (value) {
case 'Absolute': return 'absolute';
case 'Relative': return 'relative';
default: throw new Error("Unknown position value: " + value);
}
}
function directionMarkupValue(value) {
switch (value) {
case 'Ltr': return 'ltr';
case 'Rtl': return 'rtl';
case 'Inherit': return 'inherit';
}
}
function alignMarkupValue(value) {
switch (value) {
case 'AlignAuto': return 'auto';
case 'AlignCenter': return 'center';
case 'AlignStretch': return 'stretch';
case 'AlignFlexStart': return 'flex-start';
case 'AlignFlexEnd': return 'flex-end';
}
}
function pixelMarkupValue(fixedEncodingValue) {
switch (fixedEncodingValue) {
case 'cssUndefined': return 'auto';
default:
return (fixedEncodingValue / unitsPerPixel) + 'px';
}
}
/**
* Returns a structure that mirrors the test data.
*/
function getExpectedResults(testData, computedKeyPathSoFar) {
var ret = {};
forEachTestData(testData, computedKeyPathSoFar, (testDataItem, testKey, totalKeyPath) => {
let domNode = document.getElementById(totalKeyPath);
ret[testKey] = {
expectedLayout: {
left: domNode.offsetLeft + domNode.parentNode.clientLeft,
top: domNode.offsetTop + domNode.parentNode.clientTop,
width: domNode.offsetWidth,
height: domNode.offsetHeight,
},
children: testData[testKey].children ? getExpectedResults(testData[testKey].children, totalKeyPath) : null
};
});
return ret;
}
/* Supported:
<div id="flex_grow_within_max_width" style="width: 200px; height: 100px;">
<div style="flex-direction: row; max-width: 100px;">
<div style=" flex-grow: 1; height: 20px;"></div>
</div>
</div>
<div id="flex_grow_within_constrained_max_width" style="width: 200px; height: 100px;">
<div style="flex-direction: row; max-width: 300px;">
<div style=" flex-grow: 1; height: 20px;"></div>
</div>
</div>
<div id="justify_content_overflow_min_max" style="justify-content: center; min-height: 100px; max-height: 110px; ">
<div style="width: 50px; height: 50px;"></div>
<div style="width: 50px; height: 50px;"></div>
<div style="width: 50px; height: 50px;"></div>
</div>
<div id="justify_content_min_max" style="justify-content: center; width: 100px; min-height: 100px; max-height: 200px; ">
<div style="width: 60px; height: 60px;"></div>
</div>
<div id="align_items_min_max" style="align-items: center; height: 100px; min-width: 100px; max-width: 200px;">
<div style="width: 60px; height: 60px;"></div>
</div>
<div id="align_items_stretch" style="width: 100px; height: 100px;">
<div style="height: 10px;"></div>
</div>
<div id="align_items_center" style="align-items: center; width: 100px; height: 100px; ">
<div style="width: 10px; height: 10px;"></div>
</div>
<div id="align_items_flex_start" style="align-items: flex-start; width: 100px; height: 100px; ">
<div style="width: 10px; height: 10px;"></div>
</div>
<div id="align_items_flex_end" style="align-items: flex-end; width: 100px; height: 100px; ">
<div style="width: 10px;height: 10px; "></div>
</div>
<div id="align_self_center" style="width:100px; height: 100px;">
<div style=" align-self: center; width: 10px; height: 10px;"></div>
</div>
<div id="align_self_flex_end" style="width:100px; height: 100px;">
<div style="align-self: flex-end; width: 10px; height: 10px; "></div>
</div>
<div id="align_self_flex_start" style="width:100px; height: 100px;">
<div style="align-self: flex-start; width: 10px; height: 10px;"></div>
</div>
<div id="align_self_flex_end_override_flex_start" style="align-items: flex-start; width:100px; height: 100px; ">
<div style="align-self: flex-end; width: 10px; height: 10px; "></div>
</div>
<div id="border_no_size" style="border-width: 10px;">
</div>
<div id="border_no_size_broken_out" style="border-left-width: 10px; border-right-width: 10px; border-top-width: 10px; border-bottom-width: 10px; ">
</div>
<div id="border_no_size_override_left" style="border-width: 20px; border-left-width: 10px;">
</div>
<div id="border_no_size_override_right" style="border-width: 20px; border-right-width: 10px;">
</div>
<div id="border_no_size_override_bottom" style="border-width: 20px; border-bottom-width: 10px;">
</div>
<div id="border_container_match_child" style="border-width: 10px;">
<div style="width: 10px; height: 10px;"></div>
</div>
<div id="border_stretch_child" style="width: 100px; height: 100px; border-width: 10px;">
<div style="height: 10px;"></div>
</div>
<div id="border_center_child" style="justify-content: center; align-items: center; width: 100px; height: 100px; border-start-width: 10px; border-top-width: 10px; border-end-width: 20px; border-bottom-width: 20px; ">
<div style="width: 10px;height: 10px;"></div>
</div>
<div id="max_width" style="width: 100px; height: 100px;">
<div style="max-width: 50px; height: 10px; "></div>
</div>
<div id="max_height" style=" flex-direction: row; width: 100px; height: 100px;">
<div style="width: 10px; max-height: 50px;"></div>
</div>
<div id="padding_no_size" style="padding: 10px;">
</div>
<div id="padding_container_match_child" style="padding: 10px;">
<div style="width: 10px; height: 10px;"></div>
</div>
<div id="padding_stretch_child" style="width: 100px; height: 100px; padding: 10px;">
<div style="height: 10px;"></div>
</div>
<div id="padding_center_child" style="justify-content: center; align-items: center; padding-top: 10px; padding-bottom: 20px; width: 100px; height: 100px; padding-start: 10px; padding-end: 20px; ">
<div style="width: 10px; height: 10px; "></div>
</div>
<div id="absolute_layout_width_height_start_top" style="width: 100px; height: 100px;">
<div style="position: absolute; top: 10px;start: 10px; width:10px; height: 10px;"></div>
</div>
<div id="absolute_layout_width_height_end_bottom" style="width: 100px; height: 100px;">
<div style="position: absolute; bottom: 10px; end: 10px; width:10px; height: 10px;"></div>
</div>
<div id="absolute_layout_start_top_end_bottom" style="width: 100px; height: 100px;">
<div style="position: absolute; start: 10px; top: 10px; end: 10px; bottom: 10px;"></div>
</div>
<div id="absolute_layout_width_height_start_top_end_bottom" style="width: 100px; height: 100px;">
<div style="width:10px; height: 10px; position: absolute; start: 10px; top: 10px; end: 10px; bottom: 10px;"></div>
</div>
<div id="do_not_clamp_height_of_absolute_node_to_height_of_its_overflow_hidden_parent" style=" flex-direction: row; overflow: hidden; width: 50px; height: 50px; ">
<div style="position: absolute; start: 0; top: 0;">
<div style="width: 100px; height: 100px;"></div>
</div>
</div>
<div id="flex_direction_column_no_height" style="width: 100px">
<div style="height: 10px;"></div>
<div style="height: 10px;"></div>
<div style="height: 10px;"></div>
</div>
<div id="flex_direction_row_no_width" style=" flex-direction: row; height: 100px;">
<div style="width: 10px;"></div>
<div style="width: 10px;"></div>
<div style="width: 10px;"></div>
</div>
<div id="flex_direction_column" style="width: 100px;height: 100px; ">
<div style="height: 10px;"></div>
<div style="height: 10px;"></div>
<div style="height: 10px;"></div>
</div>
<div id="flex_direction_row" style="flex-direction: row; width: 100px;height: 100px; ">
<div style="width: 10px;"></div>
<div style="width: 10px;"></div>
<div style="width: 10px;"></div>
</div>
<div id="flex_direction_column_reverse" style=" flex-direction: column-reverse; width: 100px; height: 100px; ">
<div style="height: 10px;"></div>
<div style="height: 10px;"></div>
<div style="height: 10px;"></div>
</div>
<div id="flex_direction_row_reverse" style=" flex-direction: row-reverse; width: 100px; height: 100px; ">
<div style="width: 10px;"></div>
<div style="width: 10px;"></div>
<div style="width: 10px;"></div>
</div>
<div id="wrap_column" style="flex-wrap: wrap; width: 60px; height: 100px;">
<div style="width: 30px; height: 30px; "></div>
<div style="width: 30px; height: 30px; "></div>
<div style="width: 30px; height: 30px; "></div>
<div style="width: 30px; height: 30px; "></div>
</div>
<div id="wrap_row" style="flex-wrap: wrap; flex-direction: row; width: 100px;">
<div style="width: 30px; height: 30px; "></div>
<div style="width: 30px; height: 30px; "></div>
<div style="width: 30px; height: 30px; "></div>
<div style="width: 30px; height: 30px; "></div>
</div>
<div id="wrap_row_align_items_flex_end" style=" flex-direction: row; align-items: flex-end; flex-wrap: wrap; width: 100px;">
<div style="width: 30px; height: 10px; "></div>
<div style="width: 30px; height: 20px; "></div>
<div style="width: 30px; height: 30px; "></div>
<div style="width: 30px; height: 30px; "></div>
</div>
<div id="wrap_row_align_items_center" style=" flex-direction: row; align-items: center; flex-wrap: wrap; width: 100px;">
<div style="width: 30px; height: 10px; "></div>
<div style="width: 30px; height: 20px; "></div>
<div style="width: 30px; height: 30px; "></div>
<div style="width: 30px; height: 30px; "></div>
</div>
<div id="margin_start" style="flex-direction: row; width: 100px; height: 100px; ">
<div style="width: 10px; margin-start: 10px;"></div>
</div>
<div id="margin_end" style="flex-direction: row; justify-content: flex-end; width: 100px; height: 100px; ">
<div style="width: 10px; margin-end: 10px;"></div>
</div>
<div id="margin_left" style=" flex-direction: row; width: 100px; height: 100px;">
<div style="width: 10px; margin-left: 10px;"></div>
</div>
<div id="margin_top" style="width: 100px; height: 100px;">
<div style="height: 10px; margin-top: 10px;"></div>
</div>
<div id="margin_right" style="flex-direction: row; justify-content: flex-end; width: 100px; height: 100px; ">
<div style="width: 10px; margin-right: 10px;"></div>
</div>
<div id="margin_bottom" style=" justify-content: flex-end; width: 100px; height: 100px;">
<div style="height: 10px; margin-bottom: 10px;"></div>
</div>
<div id="align_content_flex_start" style="flex-direction: column; align-content: flex-start; width: 100px; height: 100px; flex-wrap: wrap; ">
<div style="width: 50px; height: 10px;"></div>
<div style="width: 50px; height: 10px;"></div>
<div style="width: 50px; height: 10px;"></div>
<div style="width: 50px; height: 10px;"></div>
<div style="width: 50px; height: 10px;"></div>
</div>
<div id="align_content_flex_end" style="flex-direction: column; align-content: flex-end; flex-wrap: wrap; width: 100px; height: 100px;">
<div style="width: 50px; height: 10px;"></div>
<div style="width: 50px; height: 10px;"></div>
<div style="width: 50px; height: 10px;"></div>
<div style="width: 50px; height: 10px;"></div>
<div style="width: 50px; height: 10px;"></div>
</div>
<div id="align_content_center" style=" flex-direction: column; align-content: center; flex-wrap: wrap;width: 100px; height: 100px;">
<div style="width: 50px; height: 10px;"></div>
<div style="width: 50px; height: 10px;"></div>
<div style="width: 50px; height: 10px;"></div>
<div style="width: 50px; height: 10px;"></div>
<div style="width: 50px; height: 10px;"></div>
</div>
<div id="align_content_stretch" style="flex-direction: column; align-content: stretch;flex-wrap: wrap; width: 100px; height: 100px; ">
<div style="width: 50px;"></div>
<div style="width: 50px;"></div>
<div style="width: 50px;"></div>
<div style="width: 50px;"></div>
<div style="width: 50px;"></div>
</div>
<div id="justify_content_row_flex_start" style=" flex-direction: row; justify-content: flex-start; width: 102px; height: 102px;">
<div style="width: 10px;"></div>
<div style="width: 10px;"></div>
<div style="width: 10px;"></div>
</div>
<div id="justify_content_row_flex_end" style=" flex-direction: row; justify-content: flex-end; width: 102px; height: 102px;">
<div style="width: 10px;"></div>
<div style="width: 10px;"></div>
<div style="width: 10px;"></div>
</div>
<div id="justify_content_row_center" style="flex-direction: row; justify-content: center; width: 102px; height: 102px; ">
<div style="width: 10px;"></div>
<div style="width: 10px;"></div>
<div style="width: 10px;"></div>
</div>
<div id="justify_content_row_space_between" style=" flex-direction: row; justify-content: space-between; width: 102px; height: 102px;">
<div style="width: 10px;"></div>
<div style="width: 10px;"></div>
<div style="width: 10px;"></div>
</div>
<div id="justify_content_row_space_around" style=" flex-direction: row; justify-content: space-around; width: 102px; height: 102px;">
<div style="width: 10px;"></div>
<div style="width: 10px;"></div>
<div style="width: 10px;"></div>
</div>
<div id="justify_content_column_flex_start" style="justify-content: flex-start; width: 102px; height: 102px; ">
<div style="height: 10px;"></div>
<div style="height: 10px;"></div>
<div style="height: 10px;"></div>
</div>
<div id="justify_content_column_flex_end" style="justify-content: flex-end; width: 102px; height: 102px; ">
<div style="height: 10px;"></div>
<div style="height: 10px;"></div>
<div style="height: 10px;"></div>
</div>
<div id="justify_content_column_center" style="justify-content: center;width: 102px; height: 102px; ">
<div style="height: 10px;"></div>
<div style="height: 10px;"></div>
<div style="height: 10px;"></div>
</div>
<div id="justify_content_column_space_between" style="justify-content: space-between; width: 102px; height: 102px; ">
<div style="height: 10px;"></div>
<div style="height: 10px;"></div>
<div style="height: 10px;"></div>
</div>
<div id="justify_content_column_space_around" style=" justify-content: space-around; width: 102px; height: 102px;">
<div style="height: 10px;"></div>
<div style="height: 10px;"></div>
<div style="height: 10px;"></div>
</div>
<div id="border_flex_child" style="width: 100px; height: 100px; border-width: 10px;">
<div style=" flex-grow:1; width: 10px;"></div>
</div>
<div id="min_height" style="width: 100px; height: 100px;">
<div style="flex-grow: 1; min-height: 60px;"></div>
<div style="flex-grow: 1;"></div>
</div>
<div id="min_width" style="flex-direction: row; width: 100px; height: 100px; ">
<div style="flex-grow: 1; min-width: 60px;"></div>
<div style="flex-grow: 1;"></div>
</div>
<div id="padding_flex_child" style="width: 100px; height: 100px; padding: 10px;">
<div style=" flex-grow:1; width: 10px;"></div>
</div>
<div id="margin_and_flex_row" style=" flex-direction: row; width: 100px; height: 100px;">
<div style=" flex-grow: 1; margin-start: 10px; margin-end: 10px;"></div>
</div>
<div id="margin_and_flex_column" style="width: 100px; height: 100px;">
<div style=" flex-grow: 1; margin-top: 10px; margin-bottom: 10px;"></div>
</div>
<div id="margin_and_stretch_row" style=" flex-direction: row; width: 100px; height: 100px;">
<div style=" flex-grow: 1; margin-top: 10px; margin-bottom: 10px;"></div>
</div>
<div id="margin_and_stretch_column" style="width: 100px; height: 100px;">
<div style=" flex-grow: 1; margin-start: 10px; margin-end: 10px;"></div>
</div>
<div id="margin_with_sibling_row" style=" flex-direction: row; width: 100px; height: 100px;">
<div style=" flex-grow: 1; margin-end: 10px;"></div>
<div style="flex-grow: 1;"></div>
</div>
<div id="margin_with_sibling_column" style="width: 100px; height: 100px;">
<div style=" flex-grow: 1; margin-bottom: 10px;"></div>
<div style="flex-grow: 1;"></div>
</div>
<div id="flex_basis_flex_grow_column" style="width: 100px; height: 100px;">
<div style=" flex-grow: 1; flex-basis: 50px;"></div>
<div style="flex-grow: 1;"></div>
</div>
<div id="flex_basis_flex_grow_row" style=" flex-direction: row; width: 100px; height: 100px;">
<div style=" flex-grow: 1; flex-basis: 50px;"></div>
<div style="flex-grow: 1;"></div>
</div>
<div id="flex_basis_flex_shrink_column" style="width: 100px; height: 100px;">
<div style="flex-basis: 100px; flex-shrink: 1;"></div>
<div style="flex-basis: 50px;"></div>
</div>
<div id="flex_basis_flex_shrink_row" style=" flex-direction: row; width: 100px; height: 100px;">
<div style="flex-basis: 100px; flex-shrink: 1;"></div>
<div style="flex-basis: 50px;"></div>
</div>
<div id="flex_basis_flex_grow_undefined_main" style="width: 100px;">
<div style=" flex-grow: 1; flex-basis: 100px;"></div>
<div style="flex-basis: 50px;"></div>
</div>
<div id="flex_basis_flex_grow_undefined_main_w_margin_top" style="width: 100px; margin-top:10px;">
<div style=" flex-grow: 1; flex-basis: 100px;"></div>
<div style="flex-basis: 50px;"></div>
</div>
<div id="flex_basis_flex_grow_undefined_main_w_margin_bottom" style="width: 100px; margin-bottom:10px;">
<div style=" flex-grow: 1; flex-basis: 100px;"></div>
<div style="flex-basis: 50px;"></div>
</div>
<div id="flex_basis_flex_grow_undefined_main_w_margin_left" style="width: 100px; margin-left:10px;">
<div style=" flex-grow: 1; flex-basis: 100px;"></div>
<div style="flex-basis: 50px;"></div>
</div>
<div id="jwalke_border_width_only_start" style=" align-items: center; justify-content: center; width: 100px; height: 100px; border-start-width: 10px; border-top-width: 10px; border-bottom-width: 20px;">
<div style="height: 10px; width: 10px;"></div>
</div>
<div id="jwalke_border_width_only_end" style="align-items: center; justify-content: center; width: 100px; height: 100px; border-end-width: 10px; border-top-width: 10px; border-bottom-width: 20px; ">
<div style="height: 10px; width: 10px;"></div>
</div>
<div id="start_overrides_margin" style="width: 100px; height: 100px;">
<div style="
flex-grow: 1;
margin-left: 20px;
margin-right: 20px;
margin-start: 10px;"
>
</div>
</div>
<div id="end_overrides_margin" style="width: 100px; height: 100px;">
<div style="
flex-grow: 1;
margin-left: 20px;
margin-right: 20px;
margin-end: 10px;"
>
</div>
</div>
<div id="start_overrides_padding" style="width: 100px; height: 100px;">
<div style="
flex-grow: 1;
padding-left: 20px;
padding-right: 20px;
padding-start: 10px;"
>
</div>
</div>
<div id="end_overrides_padding" style="width: 100px; height: 100px;">
<div style="
flex-grow: 1;
padding-left: 20px;
padding-right: 20px;
padding-end: 10px;"
>
</div>
</div>
<div id="start_overrides_border" style="width: 100px; height: 100px;">
<div style="
flex-grow: 1;
border-left-width: 20px;
border-right-width: 20px;
border-start-width: 10px;"
>
</div>
</div>
<div id="end_overrides_border" style="width: 100px; height: 100px;">
<div style="
border-left-width: 20px;
border-right-width: 20px;
border-end-width: 10px;
flex-grow: 1;"
>
</div>
</div>
<div id="start_overrides" style="width: 100px; height: 100px;">
<div style="
position:absolute;
left: 20px;
right: 20px;
start: 10px;
flex-grow: 1;"
>
</div>
</div>
<div id="end_overrides" style="width: 100px; height: 100px;">
<div style="
position:absolute;
left: 20px;
right: 20px;
end: 10px;
flex-grow: 1;"
>
</div>
</div>
<div id="flex_shrink_to_zero" style="height: 75px;">
<div style="width: 50px; height: 50px; flex-shrink:0;"></div>
<div style="width: 50px; height: 50px; flex-shrink:1;"></div>
<div style="width: 50px; height: 50px; flex-shrink:0;"></div>
</div>
<div id="flex_basis_overrides_main_size" style="height: 100px; width: 100px;">
<div style="height: 20px; flex-grow:1; flex-basis:50px;"></div>
<div style="height: 10px; flex-grow:1;"></div>
<div style="height: 10px; flex-grow:1;"></div>
</div>
<div id="flex_grow_shrink_at_most" style="height: 100px; width: 100px;">
<div>
<div style="flex-grow:1; flex-shrink:1;"></div>
</div>
</div>
<div id='bugRepro' style='align-items:auto; padding-start: 48px; padding-end:48px; width:1408px; flex-direction: row;'>
<div style=''>
<div style=''></div>
</div>
<div style=''>
<div style=''>
<div style=''></div>
</div>
</div>
</div>
<div id='bugRepro2' style='padding-start: 10px; padding-end:10px; width:200px; flex-direction: row;'>
<div style='justify-content:flex-start; width:20px;'>
</div>
<div style='min-height: 0px; flex-direction: row; flex-grow: 1;'>
<div style='flex-grow: 1;'> </div>
</div>
</div>
*/
/*
This one doesn't work correctly in Chrome, so not sure what to do.
<div id="wrap_column" style="height: 100px; flex-wrap: wrap">
<div style="height: 30px; width: 30px;"></div>
<div style="height: 30px; width: 30px;"></div>
<div style="height: 30px; width: 30px;"></div>
<div style="height: 30px; width: 30px;"></div>
</div>
*/