Compare commits

..

1 Commits

Author SHA1 Message Date
Rob Hogan
7305a5f7c8 Update GHA actions/upload-artifact to v4, unbreak CI
Summary:
`actions/upload-artifact@v3` is deprecated and will no longer execute, causing CI to fail - eg:

https://github.com/facebook/yoga/actions/runs/13789185831/job/38564343959

See https://github.blog/changelog/2024-04-16-deprecation-notice-v3-of-the-artifact-actions/ for context

Reviewed By: NickGerleman

Differential Revision: D70986391
2025-03-11 13:02:27 -07:00
11 changed files with 16 additions and 249 deletions

View File

@@ -1,184 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <gtest/gtest.h>
#include <yoga/Yoga.h>
#include <yoga/config/Config.h>
#include <yoga/node/Node.h>
#include <functional>
#include <memory>
#include <vector>
namespace facebook::yoga {
struct YGPersistentNodeCloningTest : public ::testing::Test {
struct NodeWrapper {
explicit NodeWrapper(
YGConfigRef config,
std::vector<std::shared_ptr<NodeWrapper>> children = {})
: node{YGNodeNewWithConfig(config)}, children{std::move(children)} {
YGNodeSetContext(node, this);
auto privateNode = resolveRef(node);
for (const auto& child : this->children) {
auto privateChild = resolveRef(child->node);
// Claim first ownership of not yet owned nodes, to avoid immediately
// cloning them
if (YGNodeGetOwner(child->node) == nullptr) {
privateChild->setOwner(privateNode);
}
privateNode->insertChild(privateChild, privateNode->getChildCount());
}
}
// Clone, with current children, for mutation
NodeWrapper(const NodeWrapper& other)
: node{YGNodeClone(other.node)}, children{other.children} {
YGNodeSetContext(node, this);
auto privateNode = resolveRef(node);
privateNode->setOwner(nullptr);
}
// Clone, with new children
NodeWrapper(
const NodeWrapper& other,
std::vector<std::shared_ptr<NodeWrapper>> children)
: node{YGNodeClone(other.node)}, children{std::move(children)} {
YGNodeSetContext(node, this);
auto privateNode = resolveRef(node);
privateNode->setOwner(nullptr);
privateNode->setChildren({});
privateNode->setDirty(true);
for (const auto& child : this->children) {
auto privateChild = resolveRef(child->node);
// Claim first ownership of not yet owned nodes, to avoid immediately
// cloning them
if (YGNodeGetOwner(child->node) == nullptr) {
privateChild->setOwner(privateNode);
}
privateNode->insertChild(privateChild, privateNode->getChildCount());
}
}
NodeWrapper(NodeWrapper&&) = delete;
~NodeWrapper() {
YGNodeFree(node);
}
NodeWrapper& operator=(const NodeWrapper& other) = delete;
NodeWrapper& operator=(NodeWrapper&& other) = delete;
YGNodeRef node;
std::vector<std::shared_ptr<NodeWrapper>> children;
};
struct ConfigWrapper {
ConfigWrapper() {
YGConfigSetCloneNodeFunc(
config,
[](YGNodeConstRef oldNode, YGNodeConstRef owner, size_t childIndex) {
onClone(oldNode, owner, childIndex);
auto wrapper = static_cast<NodeWrapper*>(YGNodeGetContext(owner));
auto old = static_cast<NodeWrapper*>(YGNodeGetContext(oldNode));
wrapper->children[childIndex] = std::make_shared<NodeWrapper>(*old);
return wrapper->children[childIndex]->node;
});
}
ConfigWrapper(const ConfigWrapper&) = delete;
ConfigWrapper(ConfigWrapper&&) = delete;
~ConfigWrapper() {
YGConfigFree(config);
}
ConfigWrapper& operator=(const ConfigWrapper&) = delete;
ConfigWrapper& operator=(ConfigWrapper&&) = delete;
YGConfigRef config{YGConfigNew()};
};
ConfigWrapper configWrapper;
YGConfigRef config{configWrapper.config};
void SetUp() override {
onClone = [](...) {};
}
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
static inline std::function<void(YGNodeConstRef, YGNodeConstRef, size_t)>
onClone;
};
TEST_F(
YGPersistentNodeCloningTest,
changing_sibling_height_does_not_clone_neighbors) {
// <ScrollView>
// <View id="Sibling" style={{ height: 1 }} />
// <View id="A" style={{ height: 1 }}>
// <View id="B">
// <View id="C">
// <View id="D"/>
// </View>
// </View>
// </View>
// </ScrollView>
auto sibling = std::make_shared<NodeWrapper>(config);
YGNodeStyleSetHeight(sibling->node, 1);
auto d = std::make_shared<NodeWrapper>(config);
auto c = std::make_shared<NodeWrapper>(config, std::vector{d});
auto b = std::make_shared<NodeWrapper>(config, std::vector{c});
auto a = std::make_shared<NodeWrapper>(config, std::vector{b});
YGNodeStyleSetHeight(a->node, 1);
auto scrollContentView =
std::make_shared<NodeWrapper>(config, std::vector{sibling, a});
YGNodeStyleSetPositionType(scrollContentView->node, YGPositionTypeAbsolute);
auto scrollView =
std::make_shared<NodeWrapper>(config, std::vector{scrollContentView});
YGNodeStyleSetWidth(scrollView->node, 100);
YGNodeStyleSetHeight(scrollView->node, 100);
// We don't expect any cloning during the first layout
onClone = [](...) { FAIL(); };
YGNodeCalculateLayout(
scrollView->node, YGUndefined, YGUndefined, YGDirectionLTR);
auto siblingPrime = std::make_shared<NodeWrapper>(config);
YGNodeStyleSetHeight(siblingPrime->node, 2);
auto scrollContentViewPrime = std::make_shared<NodeWrapper>(
*scrollContentView, std::vector{siblingPrime, a});
auto scrollViewPrime = std::make_shared<NodeWrapper>(
*scrollView, std::vector{scrollContentViewPrime});
std::vector<NodeWrapper*> nodesCloned;
// We should only need to clone "A"
onClone = [&](YGNodeConstRef oldNode,
YGNodeConstRef /*owner*/,
size_t /*childIndex*/) {
nodesCloned.push_back(static_cast<NodeWrapper*>(YGNodeGetContext(oldNode)));
};
YGNodeCalculateLayout(
scrollViewPrime->node, YGUndefined, YGUndefined, YGDirectionLTR);
EXPECT_EQ(nodesCloned.size(), 1);
EXPECT_EQ(nodesCloned[0], a.get());
}
} // namespace facebook::yoga

View File

@@ -161,23 +161,3 @@ TEST(YogaTest, per_node_point_scale_factor) {
YGConfigFree(config2);
YGConfigFree(config3);
}
TEST(YogaTest, raw_layout_dimensions) {
YGConfigRef config = YGConfigNew();
YGConfigSetPointScaleFactor(config, 0.5f);
YGNodeRef root = YGNodeNewWithConfig(config);
YGNodeStyleSetWidth(root, 11.5f);
YGNodeStyleSetHeight(root, 9.5f);
YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR);
ASSERT_EQ(YGNodeLayoutGetWidth(root), 12.0f);
ASSERT_EQ(YGNodeLayoutGetHeight(root), 10.0f);
ASSERT_EQ(YGNodeLayoutGetRawWidth(root), 11.5f);
ASSERT_EQ(YGNodeLayoutGetRawHeight(root), 9.5f);
YGNodeFreeRecursive(root);
YGConfigFree(config);
}

View File

@@ -17,15 +17,15 @@ has effect when items are wrapped to multiple lines using [flex wrap](/docs/styl
**Center**: Align wrapped lines in the center of the container's cross axis.
**Space between**: Evenly space wrapped lines across the container's cross axis, distributing
**Space between**: Evenly space wrapped lines across the container's main axis, distributing
remaining space between the lines.
**Space around**: Evenly space wrapped lines across the container's cross axis, distributing
**Space around**: Evenly space wrapped lines across the container's main axis, distributing
remaining space around the lines. Compared to space between using
space around will result in space being distributed to the beginning of
the first lines and end of the last line.
**Space evenly**: Evenly space wrapped lines across the container's cross axis, distributing
**Space evenly**: Evenly space wrapped lines across the container's main axis, distributing
remaining space around the lines. Compared to space around, space evenly will not
double the gaps between children. The size of gaps between children and between
the parent's edges and the first/last child will all be equal.

View File

@@ -90,11 +90,3 @@ float YGNodeLayoutGetPadding(YGNodeConstRef node, YGEdge edge) {
return getResolvedLayoutProperty<&LayoutResults::padding>(
node, scopedEnum(edge));
}
float YGNodeLayoutGetRawHeight(YGNodeConstRef node) {
return resolveRef(node)->getLayout().rawDimension(Dimension::Height);
}
float YGNodeLayoutGetRawWidth(YGNodeConstRef node) {
return resolveRef(node)->getLayout().rawDimension(Dimension::Width);
}

View File

@@ -32,14 +32,4 @@ YG_EXPORT float YGNodeLayoutGetMargin(YGNodeConstRef node, YGEdge edge);
YG_EXPORT float YGNodeLayoutGetBorder(YGNodeConstRef node, YGEdge edge);
YG_EXPORT float YGNodeLayoutGetPadding(YGNodeConstRef node, YGEdge edge);
/**
* Return the measured height of the node, before layout rounding
*/
YG_EXPORT float YGNodeLayoutGetRawHeight(YGNodeConstRef node);
/**
* Return the measured width of the node, before layout rounding
*/
YG_EXPORT float YGNodeLayoutGetRawWidth(YGNodeConstRef node);
YG_EXTERN_C_END

View File

@@ -106,25 +106,25 @@ void roundLayoutResultsToPixelGrid(
const bool hasFractionalHeight =
!yoga::inexactEquals(round(scaledNodeHeight), scaledNodeHeight);
node->getLayout().setDimension(
Dimension::Width,
node->setLayoutDimension(
roundValueToPixelGrid(
absoluteNodeRight,
pointScaleFactor,
(textRounding && hasFractionalWidth),
(textRounding && !hasFractionalWidth)) -
roundValueToPixelGrid(
absoluteNodeLeft, pointScaleFactor, false, textRounding));
absoluteNodeLeft, pointScaleFactor, false, textRounding),
Dimension::Width);
node->getLayout().setDimension(
Dimension::Height,
node->setLayoutDimension(
roundValueToPixelGrid(
absoluteNodeBottom,
pointScaleFactor,
(textRounding && hasFractionalHeight),
(textRounding && !hasFractionalHeight)) -
roundValueToPixelGrid(
absoluteNodeTop, pointScaleFactor, false, textRounding));
absoluteNodeTop, pointScaleFactor, false, textRounding),
Dimension::Height);
}
for (yoga::Node* child : node->getChildren()) {

View File

@@ -27,7 +27,7 @@ enum class SizingMode {
StretchFit,
/**
* A box's "ideal" size in a given axis when given infinite available space.
* A boxs ideal size in a given axis when given infinite available space.
* Usually this is the smallest size the box could take in that axis while
* still fitting around its contents, i.e. minimizing unfilled space while
* avoiding overflow.

View File

@@ -19,7 +19,6 @@ namespace facebook::yoga {
#if defined(__cpp_exceptions)
throw std::logic_error(message);
#else
static_cast<void>(message); // Unused
std::terminate();
#endif
}

View File

@@ -36,12 +36,12 @@ enum struct LayoutPassReason : int {
};
struct LayoutData {
int layouts = 0;
int measures = 0;
uint32_t maxMeasureCache = 0;
int cachedLayouts = 0;
int cachedMeasures = 0;
int measureCallbacks = 0;
int layouts;
int measures;
uint32_t maxMeasureCache;
int cachedLayouts;
int cachedMeasures;
int measureCallbacks;
std::array<int, static_cast<uint8_t>(LayoutPassReason::COUNT)>
measureCallbackReasonsCount;
};

View File

@@ -66,18 +66,10 @@ struct LayoutResults {
return measuredDimensions_[yoga::to_underlying(axis)];
}
float rawDimension(Dimension axis) const {
return rawDimensions_[yoga::to_underlying(axis)];
}
void setMeasuredDimension(Dimension axis, float dimension) {
measuredDimensions_[yoga::to_underlying(axis)] = dimension;
}
void setRawDimension(Dimension axis, float dimension) {
rawDimensions_[yoga::to_underlying(axis)] = dimension;
}
float position(PhysicalEdge physicalEdge) const {
return position_[yoga::to_underlying(physicalEdge)];
}
@@ -121,7 +113,6 @@ struct LayoutResults {
std::array<float, 2> dimensions_ = {{YGUndefined, YGUndefined}};
std::array<float, 2> measuredDimensions_ = {{YGUndefined, YGUndefined}};
std::array<float, 2> rawDimensions_ = {{YGUndefined, YGUndefined}};
std::array<float, 4> position_ = {};
std::array<float, 4> margin_ = {};
std::array<float, 4> border_ = {};

View File

@@ -247,7 +247,6 @@ void Node::setLayoutHadOverflow(bool hadOverflow) {
void Node::setLayoutDimension(float lengthValue, Dimension dimension) {
layout_.setDimension(dimension, lengthValue);
layout_.setRawDimension(dimension, lengthValue);
}
// If both left and right are defined, then use left. Otherwise return +left or