Files
yoga/gentest/gentest.js
Emil Sjolander 3db38f2a80 Remove rounding from experimental features
Summary: Rounding has been successfully adopted by multiple products and frameworks. Time to move it out of experimental mode. Rounding can still be turned of by setting the point scale factor to 0 on the config.

Reviewed By: gkassabli

Differential Revision: D4953838

fbshipit-source-id: 3ee5f27d92f95b3ed4a01c98bc35e9157f2e91c5
2017-04-27 07:14:29 -07:00

538 lines
17 KiB
JavaScript
Executable File

/**
* 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.
*/
window.onload = function() {
checkDefaultValues();
printTest(
new CPPEmitter(),
document.body.children[0],
document.body.children[1],
document.body.children[2]);
printTest(
new JavaEmitter(),
document.body.children[0],
document.body.children[1],
document.body.children[2]);
printTest(
new CSEmitter(),
document.body.children[0],
document.body.children[1],
document.body.children[2]);
printTest(
new JavascriptEmitter(),
document.body.children[0],
document.body.children[1],
document.body.children[2]);
}
function assert(condition, message) {
if (!condition) {
throw new Error(message);
}
}
function printTest(e, LTRContainer, RTLContainer, genericContainer) {
e.push([
'/**',
' * 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.',
' */',
'',
'// @Generated by gentest/gentest.rb from gentest/fixtures/' + document.title + '.html',
'',
]);
e.emitPrologue();
var LTRLayoutTree = calculateTree(LTRContainer);
var RTLLayoutTree = calculateTree(RTLContainer);
var genericLayoutTree = calculateTree(genericContainer);
for (var i = 0; i < genericLayoutTree.length; i++) {
e.emitTestPrologue(genericLayoutTree[i].name, genericLayoutTree[i].experiments);
if (genericLayoutTree[i].name == 'wrap_column') {
// Modify width and left values due to both safari and chrome not abiding by the
// specification. The undefined dimension of a parent should be defined by the total size
// of their children in that dimension.
// See diagram under flex-wrap header https://www.w3.org/TR/css-flexbox-1/
assert(LTRLayoutTree[0].width == 30, 'wrap_column LTR root.width should be 30');
LTRLayoutTree[0].width = 60;
assert(RTLLayoutTree[0].width == 30, 'wrap_column RTL root.width should be 30');
RTLLayoutTree[0].width = 60;
var children = RTLLayoutTree[0].children;
assert(children[0].left == 0, 'wrap_column RTL root_child0.left should be 0');
children[0].left = 30;
assert(children[1].left == 0, 'wrap_column RTL root_child0.left should be 0');
children[1].left = 30;
assert(children[2].left == 0, 'wrap_column RTL root_child2.left should be 0');
children[2].left = 30;
assert(children[3].left == -30, 'wrap_column RTL root_child3.left should be -30');
children[3].left = 0;
}
setupTestTree(
e,
undefined,
LTRLayoutTree[i],
genericLayoutTree[i],
'root',
null);
e.YGNodeCalculateLayout('root', e.YGDirectionLTR, genericLayoutTree[i].experiments);
e.push('');
assertTestTree(e, LTRLayoutTree[i], 'root', null);
e.push('');
e.YGNodeCalculateLayout('root', e.YGDirectionRTL, genericLayoutTree[i].experiments);
e.push('');
assertTestTree(e, RTLLayoutTree[i], 'root', null);
e.emitTestEpilogue(genericLayoutTree[i].experiments);
}
e.emitEpilogue();
e.print();
}
function assertTestTree(e, node, nodeName, parentName) {
e.AssertEQ(node.left, e.YGNodeLayoutGetLeft(nodeName));
e.AssertEQ(node.top, e.YGNodeLayoutGetTop(nodeName));
e.AssertEQ(node.width, e.YGNodeLayoutGetWidth(nodeName));
e.AssertEQ(node.height, e.YGNodeLayoutGetHeight(nodeName));
for (var i = 0; i < node.children.length; i++) {
e.push('');
var childName = nodeName + '_child' + i;
assertTestTree(e, node.children[i], childName, nodeName);
}
}
function checkDefaultValues() {
// Sanity check of the Yoga default values by test-template.html
[
{style:'flex-direction', value:'column'},
{style:'justify-content', value:'flex-start'},
{style:'align-content', value:'flex-start'},
{style:'align-items', value:'stretch'},
{style:'position', value:'relative'},
{style:'flex-wrap', value:'nowrap'},
{style:'overflow', value:'visible'},
{style:'flex-grow', value:'0'},
{style:'flex-shrink', value:'0'},
{style:'left', value:'undefined'},
{style:'top', value:'undefined'},
{style:'right', value:'undefined'},
{style:'bottom', value:'undefined'},
{style:'display', value:'flex'},
].forEach(function(item) {
assert(item.value === getDefaultStyleValue(item.style),
item.style + ' should be ' + item.value);
});
}
function setupTestTree(e, parent, node, genericNode, nodeName, parentName, index) {
e.emitTestTreePrologue(nodeName);
for (var style in node.style) {
// Skip position info for root as it messes up tests
if (node.declaredStyle[style] === "" &&
(style == 'position' ||
style == 'left' ||
style == 'top' ||
style == 'right' ||
style == 'bottom' ||
style == 'width' ||
style == 'height')) {
continue;
}
if (node.style[style] !== getDefaultStyleValue(style)) {
switch (style) {
case 'direction':
e.YGNodeStyleSetDirection(nodeName, directionValue(e, node.style[style]));
break;
case 'flex-direction':
e.YGNodeStyleSetFlexDirection(nodeName, flexDirectionValue(e, node.style[style]));
break;
case 'justify-content':
e.YGNodeStyleSetJustifyContent(nodeName, justifyValue(e, node.style[style]));
break;
case 'align-content':
e.YGNodeStyleSetAlignContent(nodeName, alignValue(e, node.style[style]));
break;
case 'align-items':
e.YGNodeStyleSetAlignItems(nodeName, alignValue(e, node.style[style]));
break;
case 'align-self':
if (!parent || node.style[style] !== parent.style['align-items']) {
e.YGNodeStyleSetAlignSelf(nodeName, alignValue(e, node.style[style]));
}
break;
case 'position':
e.YGNodeStyleSetPositionType(nodeName, positionValue(e, node.style[style]));
break;
case 'flex-wrap':
e.YGNodeStyleSetFlexWrap(nodeName, wrapValue(e, node.style[style]));
break;
case 'overflow':
e.YGNodeStyleSetOverflow(nodeName, overflowValue(e, node.style[style]));
break;
case 'flex-grow':
e.YGNodeStyleSetFlexGrow(nodeName, node.style[style]);
break;
case 'flex-shrink':
e.YGNodeStyleSetFlexShrink(nodeName, node.style[style]);
break;
case 'flex-basis':
e.YGNodeStyleSetFlexBasis(nodeName, pointValue(e, node.style[style]));
break;
case 'left':
if (genericNode.rawStyle.indexOf('start:') >= 0) {
e.YGNodeStyleSetPosition(nodeName, e.YGEdgeStart, pointValue(e, node.style[style]));
} else {
e.YGNodeStyleSetPosition(nodeName, e.YGEdgeLeft, pointValue(e, node.style[style]));
}
break;
case 'top':
e.YGNodeStyleSetPosition(nodeName, e.YGEdgeTop, pointValue(e, node.style[style]));
break;
case 'right':
if (genericNode.rawStyle.indexOf('end:') >= 0) {
e.YGNodeStyleSetPosition(nodeName, e.YGEdgeEnd, pointValue(e, node.style[style]));
} else {
e.YGNodeStyleSetPosition(nodeName, e.YGEdgeRight, pointValue(e, node.style[style]));
}
break;
case 'bottom':
e.YGNodeStyleSetPosition(nodeName, e.YGEdgeBottom, pointValue(e, node.style[style]));
break;
case 'margin-left':
if (genericNode.rawStyle.indexOf('margin-start:') >= 0) {
e.YGNodeStyleSetMargin(nodeName, e.YGEdgeStart, pointValue(e, node.style[style]));
} else {
e.YGNodeStyleSetMargin(nodeName, e.YGEdgeLeft, pointValue(e, node.style[style]));
}
break;
case 'margin-top':
e.YGNodeStyleSetMargin(nodeName, e.YGEdgeTop, pointValue(e, node.style[style]));
break;
case 'margin-right':
if (genericNode.rawStyle.indexOf('margin-end:') >= 0) {
e.YGNodeStyleSetMargin(nodeName, e.YGEdgeEnd, pointValue(e, node.style[style]));
} else {
e.YGNodeStyleSetMargin(nodeName, e.YGEdgeRight, pointValue(e, node.style[style]));
}
break;
case 'margin-bottom':
e.YGNodeStyleSetMargin(nodeName, e.YGEdgeBottom, pointValue(e, node.style[style]));
break;
case 'padding-left':
if (genericNode.rawStyle.indexOf('padding-start:') >= 0) {
e.YGNodeStyleSetPadding(nodeName, e.YGEdgeStart, pointValue(e, node.style[style]));
} else {
e.YGNodeStyleSetPadding(nodeName, e.YGEdgeLeft, pointValue(e, node.style[style]));
}
break;
case 'padding-top':
e.YGNodeStyleSetPadding(nodeName, e.YGEdgeTop, pointValue(e, node.style[style]));
break;
case 'padding-right':
if (genericNode.rawStyle.indexOf('padding-end:') >= 0) {
e.YGNodeStyleSetPadding(nodeName, e.YGEdgeEnd, pointValue(e, node.style[style]));
} else {
e.YGNodeStyleSetPadding(nodeName, e.YGEdgeRight, pointValue(e, node.style[style]));
}
break;
case 'padding-bottom':
e.YGNodeStyleSetPadding(nodeName, e.YGEdgeBottom, pointValue(e, node.style[style]));
break;
case 'border-left-width':
if (genericNode.rawStyle.indexOf('border-start-width:') >= 0) {
e.YGNodeStyleSetBorder(nodeName, e.YGEdgeStart, pointValue(e, node.style[style]));
} else {
e.YGNodeStyleSetBorder(nodeName, e.YGEdgeLeft, pointValue(e, node.style[style]));
}
break;
case 'border-top-width':
e.YGNodeStyleSetBorder(nodeName, e.YGEdgeTop, pointValue(e, node.style[style]));
break;
case 'border-right-width':
if (genericNode.rawStyle.indexOf('border-end-width:') >= 0) {
e.YGNodeStyleSetBorder(nodeName, e.YGEdgeEnd, pointValue(e, node.style[style]));
} else {
e.YGNodeStyleSetBorder(nodeName, e.YGEdgeRight, pointValue(e, node.style[style]));
}
break;
case 'border-bottom-width':
e.YGNodeStyleSetBorder(nodeName, e.YGEdgeBottom, pointValue(e, node.style[style]));
break;
case 'width':
e.YGNodeStyleSetWidth(nodeName, pointValue(e, node.style[style]));
break;
case 'min-width':
e.YGNodeStyleSetMinWidth(nodeName, pointValue(e, node.style[style]));
break;
case 'max-width':
e.YGNodeStyleSetMaxWidth(nodeName, pointValue(e, node.style[style]));
break;
case 'height':
e.YGNodeStyleSetHeight(nodeName, pointValue(e, node.style[style]));
break;
case 'min-height':
e.YGNodeStyleSetMinHeight(nodeName, pointValue(e, node.style[style]));
break;
case 'max-height':
e.YGNodeStyleSetMaxHeight(nodeName, pointValue(e, node.style[style]));
break;
case 'display':
e.YGNodeStyleSetDisplay(nodeName, displayValue(e, node.style[style]))
break;
}
}
}
if (parentName) {
e.YGNodeInsertChild(parentName, nodeName, index);
}
for (var i = 0; i < node.children.length; i++) {
e.push('');
var childName = nodeName + '_child' + i;
setupTestTree(
e,
node,
node.children[i],
genericNode.children[i],
childName,
nodeName,
i);
}
}
function overflowValue(e, value) {
switch (value) {
case 'visible': return e.YGOverflowVisible;
case 'hidden': return e.YGOverflowHidden;
}
}
function wrapValue(e, value) {
switch (value) {
case 'wrap': return e.YGWrapWrap;
case 'wrap-reverse': return e.YGWrapWrapReverse;
case 'nowrap': return e.YGWrapNoWrap;
}
}
function flexDirectionValue(e, value) {
switch (value) {
case 'row': return e.YGFlexDirectionRow;
case 'row-reverse': return e.YGFlexDirectionRowReverse;
case 'column': return e.YGFlexDirectionColumn;
case 'column-reverse': return e.YGFlexDirectionColumnReverse;
}
}
function justifyValue(e, value) {
switch (value) {
case 'center': return e.YGJustifyCenter;
case 'space-around': return e.YGJustifySpaceAround;
case 'space-between': return e.YGJustifySpaceBetween;
case 'flex-start': return e.YGJustifyFlexStart;
case 'flex-end': return e.YGJustifyFlexEnd;
}
}
function positionValue(e, value) {
switch (value) {
case 'absolute': return e.YGPositionTypeAbsolute;
default: return e.YGPositionTypeRelative
}
}
function directionValue(e, value) {
switch (value) {
case 'ltr': return e.YGDirectionLTR;
case 'rtl': return e.YGDirectionRTL;
case 'inherit': return e.YGDirectionInherit;
}
}
function alignValue(e, value) {
switch (value) {
case 'auto': return e.YGAlignAuto;
case 'center': return e.YGAlignCenter;
case 'stretch': return e.YGAlignStretch;
case 'flex-start': return e.YGAlignFlexStart;
case 'flex-end': return e.YGAlignFlexEnd;
case 'space-between': return e.YGAlignSpaceBetween;
case 'space-around': return e.YGAlignSpaceAround;
case 'baseline': return e.YGAlignBaseline;
}
}
function pointValue(e, value) {
switch (value) {
case 'auto': return e.YGAuto;
case 'undefined': return e.YGUndefined;
default: return value;
}
}
function displayValue(e, value){
switch(value){
case 'flex': return e.YGDisplayFlex;
case 'none': return e.YGDisplayNone;
}
}
function getDefaultStyleValue(style) {
if (style == 'position') {
return 'relative';
}
switch (style) {
case 'left':
case 'top':
case 'right':
case 'bottom':
case 'start':
case 'end':
return 'undefined';
}
var node = document.getElementById('default');
return getComputedStyle(node, null).getPropertyValue(style);
}
function getRoundedSize(node) {
var boundingRect = node.getBoundingClientRect();
return {
width: Math.round(boundingRect.right) - Math.round(boundingRect.left),
height: Math.round(boundingRect.bottom) - Math.round(boundingRect.top)
};
}
function calculateTree(root, roundToPixelGrid) {
var rootLayout = [];
for (var i = 0; i < root.children.length; i++) {
var child = root.children[i];
var layout = {
name: child.id !== '' ? child.id : 'INSERT_NAME_HERE',
left: child.offsetLeft + child.parentNode.clientLeft,
top: child.offsetTop + child.parentNode.clientTop,
width: child.offsetWidth,
height: child.offsetHeight,
children: calculateTree(child, roundToPixelGrid),
style: getYogaStyle(child),
declaredStyle: child.style,
rawStyle: child.getAttribute('style'),
experiments: child.getAttribute('experiments')
? child.getAttribute('experiments').split(' ')
: [],
};
var size = getRoundedSize(child);
layout.width = size.width;
layout.height = size.height;
rootLayout.push(layout);
}
return rootLayout;
}
function getYogaStyle(node) {
return [
'direction',
'flex-direction',
'justify-content',
'align-content',
'align-items',
'align-self',
'position',
'flex-wrap',
'overflow',
'flex-grow',
'flex-shrink',
'flex-basis',
'left',
'top',
'right',
'bottom',
'margin-left',
'margin-top',
'margin-right',
'margin-bottom',
'padding-left',
'padding-top',
'padding-right',
'padding-bottom',
'border-left-width',
'border-top-width',
'border-right-width',
'border-bottom-width',
'width',
'min-width',
'max-width',
'height',
'min-height',
'max-height',
'display',
].reduce(function(map, key) {
map[key] = node.style[key] || getComputedStyle(node, null).getPropertyValue(key);
return map;
}, {});
}
var Emitter = function(lang, indent) {
this.lang = lang;
this.indent = indent;
this.indents = [];
this.lines = [];
};
Emitter.prototype = Object.create(Object.prototype, {
constructor:{value:Emitter},
pushIndent:{value:function() {
this.indents.push(this.indent);
}},
popIndent:{value:function() {
this.indents.pop();
}},
push:{value:function(line) {
if (line instanceof Array) {
line.forEach(function(element) {
this.push(element);
}, this);
return;
} else if (line.length > 0) {
line = this.indents.join('') + line;
}
this.lines.push(line);
}},
print:{value:function() {
console.log(this.lines.join('\n'));
}},
});