Skip to content

Commit

Permalink
const-correctness fixes
Browse files Browse the repository at this point in the history
Summary:
This changes public Yoga API to in more places accept const structures where before they required mutable ones.

This tries to avoid more breaking changes yet, e.g. changing callbacks to require clients do not modify nodes when they are passed for logging. We also don't have const variants for returning child structures which would allow mutation of dependencies of the const object. These would need new names under the public API, since we do not have operator overloading in C.

Differential Revision: D49130412

fbshipit-source-id: 2ff31d3da6d2b871dde2776f2e73ee9214c4df52
  • Loading branch information
NickGerleman authored and facebook-github-bot committed Sep 12, 2023
1 parent 2a48c95 commit cacb81d
Show file tree
Hide file tree
Showing 13 changed files with 230 additions and 228 deletions.
257 changes: 118 additions & 139 deletions packages/react-native/ReactCommon/yoga/yoga/Yoga.cpp

Large diffs are not rendered by default.

56 changes: 28 additions & 28 deletions packages/react-native/ReactCommon/yoga/yoga/Yoga.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ typedef struct YGSize {
} YGSize;

typedef struct YGConfig* YGConfigRef;
typedef const struct YGConfig* YGConfigConstRef;

typedef struct YGNode* YGNodeRef;
typedef const struct YGNode* YGNodeConstRef;
Expand Down Expand Up @@ -82,7 +83,7 @@ WIN_EXPORT void YGNodeSetIsReferenceBaseline(
YGNodeRef node,
bool isReferenceBaseline);

WIN_EXPORT bool YGNodeIsReferenceBaseline(YGNodeRef node);
WIN_EXPORT bool YGNodeIsReferenceBaseline(YGNodeConstRef node);

WIN_EXPORT void YGNodeCalculateLayout(
YGNodeRef node,
Expand All @@ -104,7 +105,7 @@ WIN_EXPORT void YGNodeMarkDirty(YGNodeRef node);
// `YGCalculateLayout` will cause the recalculation of each and every node.
WIN_EXPORT void YGNodeMarkDirtyAndPropagateToDescendants(YGNodeRef node);

WIN_EXPORT void YGNodePrint(YGNodeRef node, YGPrintOptions options);
WIN_EXPORT void YGNodePrint(YGNodeConstRef node, YGPrintOptions options);

WIN_EXPORT bool YGFloatIsUndefined(float value);

Expand All @@ -125,27 +126,27 @@ WIN_EXPORT bool YGNodeCanUseCachedMeasurement(
float marginColumn,
YGConfigRef config);

WIN_EXPORT void YGNodeCopyStyle(YGNodeRef dstNode, YGNodeRef srcNode);
WIN_EXPORT void YGNodeCopyStyle(YGNodeRef dstNode, YGNodeConstRef srcNode);

WIN_EXPORT void* YGNodeGetContext(YGNodeRef node);
WIN_EXPORT void* YGNodeGetContext(YGNodeConstRef node);
WIN_EXPORT void YGNodeSetContext(YGNodeRef node, void* context);

WIN_EXPORT YGConfigRef YGNodeGetConfig(YGNodeRef node);
WIN_EXPORT void YGNodeSetConfig(YGNodeRef node, YGConfigRef config);

void YGConfigSetPrintTreeFlag(YGConfigRef config, bool enabled);
bool YGNodeHasMeasureFunc(YGNodeRef node);
bool YGNodeHasMeasureFunc(YGNodeConstRef node);
WIN_EXPORT void YGNodeSetMeasureFunc(YGNodeRef node, YGMeasureFunc measureFunc);
bool YGNodeHasBaselineFunc(YGNodeRef node);
bool YGNodeHasBaselineFunc(YGNodeConstRef node);
void YGNodeSetBaselineFunc(YGNodeRef node, YGBaselineFunc baselineFunc);
YGDirtiedFunc YGNodeGetDirtiedFunc(YGNodeRef node);
YGDirtiedFunc YGNodeGetDirtiedFunc(YGNodeConstRef node);
void YGNodeSetDirtiedFunc(YGNodeRef node, YGDirtiedFunc dirtiedFunc);
void YGNodeSetPrintFunc(YGNodeRef node, YGPrintFunc printFunc);
WIN_EXPORT bool YGNodeGetHasNewLayout(YGNodeRef node);
WIN_EXPORT bool YGNodeGetHasNewLayout(YGNodeConstRef node);
WIN_EXPORT void YGNodeSetHasNewLayout(YGNodeRef node, bool hasNewLayout);
YGNodeType YGNodeGetNodeType(YGNodeRef node);
YGNodeType YGNodeGetNodeType(YGNodeConstRef node);
void YGNodeSetNodeType(YGNodeRef node, YGNodeType nodeType);
WIN_EXPORT bool YGNodeIsDirty(YGNodeRef node);
WIN_EXPORT bool YGNodeIsDirty(YGNodeConstRef node);

WIN_EXPORT void YGNodeStyleSetDirection(YGNodeRef node, YGDirection direction);
WIN_EXPORT YGDirection YGNodeStyleGetDirection(YGNodeConstRef node);
Expand Down Expand Up @@ -280,30 +281,30 @@ WIN_EXPORT YGValue YGNodeStyleGetMaxHeight(YGNodeConstRef node);
WIN_EXPORT void YGNodeStyleSetAspectRatio(YGNodeRef node, float aspectRatio);
WIN_EXPORT float YGNodeStyleGetAspectRatio(YGNodeConstRef node);

WIN_EXPORT float YGNodeLayoutGetLeft(YGNodeRef node);
WIN_EXPORT float YGNodeLayoutGetTop(YGNodeRef node);
WIN_EXPORT float YGNodeLayoutGetRight(YGNodeRef node);
WIN_EXPORT float YGNodeLayoutGetBottom(YGNodeRef node);
WIN_EXPORT float YGNodeLayoutGetWidth(YGNodeRef node);
WIN_EXPORT float YGNodeLayoutGetHeight(YGNodeRef node);
WIN_EXPORT YGDirection YGNodeLayoutGetDirection(YGNodeRef node);
WIN_EXPORT bool YGNodeLayoutGetHadOverflow(YGNodeRef node);
WIN_EXPORT float YGNodeLayoutGetLeft(YGNodeConstRef node);
WIN_EXPORT float YGNodeLayoutGetTop(YGNodeConstRef node);
WIN_EXPORT float YGNodeLayoutGetRight(YGNodeConstRef node);
WIN_EXPORT float YGNodeLayoutGetBottom(YGNodeConstRef node);
WIN_EXPORT float YGNodeLayoutGetWidth(YGNodeConstRef node);
WIN_EXPORT float YGNodeLayoutGetHeight(YGNodeConstRef node);
WIN_EXPORT YGDirection YGNodeLayoutGetDirection(YGNodeConstRef node);
WIN_EXPORT bool YGNodeLayoutGetHadOverflow(YGNodeConstRef node);

// Get the computed values for these nodes after performing layout. If they were
// set using point values then the returned value will be the same as
// YGNodeStyleGetXXX. However if they were set using a percentage value then the
// returned value is the computed value used during layout.
WIN_EXPORT float YGNodeLayoutGetMargin(YGNodeRef node, YGEdge edge);
WIN_EXPORT float YGNodeLayoutGetBorder(YGNodeRef node, YGEdge edge);
WIN_EXPORT float YGNodeLayoutGetPadding(YGNodeRef node, YGEdge edge);
WIN_EXPORT float YGNodeLayoutGetMargin(YGNodeConstRef node, YGEdge edge);
WIN_EXPORT float YGNodeLayoutGetBorder(YGNodeConstRef node, YGEdge edge);
WIN_EXPORT float YGNodeLayoutGetPadding(YGNodeConstRef node, YGEdge edge);

WIN_EXPORT void YGConfigSetLogger(YGConfigRef config, YGLogger logger);
// Set this to number of pixels in 1 point to round calculation results If you
// want to avoid rounding - set PointScaleFactor to 0
WIN_EXPORT void YGConfigSetPointScaleFactor(
YGConfigRef config,
float pixelsInPoint);
WIN_EXPORT float YGConfigGetPointScaleFactor(YGConfigRef config);
WIN_EXPORT float YGConfigGetPointScaleFactor(YGConfigConstRef config);

// Yoga previously had an error where containers would take the maximum space
// possible instead of the minimum like they are supposed to. In practice this
Expand All @@ -312,7 +313,7 @@ WIN_EXPORT float YGConfigGetPointScaleFactor(YGConfigRef config);
// this behaviour.
WIN_EXPORT YG_DEPRECATED(
"Please use "
"\"YGConfigGetErrata()\"") bool YGConfigGetUseLegacyStretchBehaviour(YGConfigRef
"\"YGConfigGetErrata()\"") bool YGConfigGetUseLegacyStretchBehaviour(YGConfigConstRef
config);
WIN_EXPORT
YG_DEPRECATED(
Expand All @@ -336,26 +337,25 @@ WIN_EXPORT void YGConfigSetExperimentalFeatureEnabled(
YGExperimentalFeature feature,
bool enabled);
WIN_EXPORT bool YGConfigIsExperimentalFeatureEnabled(
YGConfigRef config,
YGConfigConstRef config,
YGExperimentalFeature feature);

// Using the web defaults is the preferred configuration for new projects. Usage
// of non web defaults should be considered as legacy.
WIN_EXPORT void YGConfigSetUseWebDefaults(YGConfigRef config, bool enabled);
WIN_EXPORT bool YGConfigGetUseWebDefaults(YGConfigRef config);
WIN_EXPORT bool YGConfigGetUseWebDefaults(YGConfigConstRef config);

WIN_EXPORT void YGConfigSetCloneNodeFunc(
YGConfigRef config,
YGCloneNodeFunc callback);

// Export only for C#
WIN_EXPORT YGConfigRef YGConfigGetDefault(void);

WIN_EXPORT void YGConfigSetContext(YGConfigRef config, void* context);
WIN_EXPORT void* YGConfigGetContext(YGConfigRef config);
WIN_EXPORT void* YGConfigGetContext(YGConfigConstRef config);

WIN_EXPORT void YGConfigSetErrata(YGConfigRef config, YGErrata errata);
WIN_EXPORT YGErrata YGConfigGetErrata(YGConfigRef config);
WIN_EXPORT YGErrata YGConfigGetErrata(YGConfigConstRef config);

WIN_EXPORT float YGRoundValueToPixelGrid(
double value,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -827,8 +827,10 @@ static void zeroOutLayoutRecursively(
node->setLayoutDimension(0, YGDimensionHeight);
node->setHasNewLayout(true);

node->iterChildrenAfterCloningIfNeeded(
zeroOutLayoutRecursively, layoutContext);
node->cloneChildrenIfNeeded(layoutContext);
for (const auto child : node->getChildren()) {
zeroOutLayoutRecursively(child, layoutContext);
}
}

static float calculateAvailableInnerDimension(
Expand Down
22 changes: 18 additions & 4 deletions packages/react-native/ReactCommon/yoga/yoga/config/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

#include <yoga/config/Config.h>
#include <yoga/node/Node.h>

namespace facebook::yoga {

Expand Down Expand Up @@ -101,15 +102,28 @@ void Config::setLogger(std::nullptr_t) {
}

void Config::log(
YGNodeRef node,
const yoga::Node* node,
YGLogLevel logLevel,
void* logContext,
const char* format,
va_list args) {
va_list args) const {
// TODO: Break log callback signatures to make them const correct

if (flags_.loggerUsesContext) {
logger_.withContext(this, node, logLevel, logContext, format, args);
logger_.withContext(
const_cast<yoga::Config*>(this),
const_cast<yoga::Node*>(node),
logLevel,
logContext,
format,
args);
} else {
logger_.noContext(this, node, logLevel, format, args);
logger_.noContext(
const_cast<yoga::Config*>(this),
const_cast<yoga::Node*>(node),
logLevel,
format,
args);
}
}

Expand Down
16 changes: 15 additions & 1 deletion packages/react-native/ReactCommon/yoga/yoga/config/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ struct YGConfig {};
namespace facebook::yoga {

class Config;
class Node;

// Whether moving a node from config "a" to config "b" should dirty previously
// calculated layout results.
Expand Down Expand Up @@ -78,7 +79,12 @@ class YOGA_EXPORT Config : public ::YGConfig {
void setLogger(YGLogger logger);
void setLogger(LogWithContextFn logger);
void setLogger(std::nullptr_t);
void log(YGNodeRef, YGLogLevel, void*, const char*, va_list);
void log(
const yoga::Node* node,
YGLogLevel logLevel,
void* logContext,
const char* format,
va_list args) const;

void setCloneNodeCallback(YGCloneNodeFunc cloneNode);
void setCloneNodeCallback(CloneWithContextFn cloneNode);
Expand Down Expand Up @@ -106,4 +112,12 @@ class YOGA_EXPORT Config : public ::YGConfig {
void* context_ = nullptr;
};

inline Config* resolveRef(const YGConfigRef ref) {
return static_cast<Config*>(ref);
}

inline const Config* resolveRef(const YGConfigConstRef ref) {
return static_cast<const Config*>(ref);
}

} // namespace facebook::yoga
26 changes: 5 additions & 21 deletions packages/react-native/ReactCommon/yoga/yoga/debug/AssertFatal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,43 +22,27 @@ namespace facebook::yoga {

void assertFatal(const bool condition, const char* message) {
if (!condition) {
yoga::log(
static_cast<yoga::Node*>(nullptr),
YGLogLevelFatal,
nullptr,
"%s\n",
message);
yoga::log(YGLogLevelFatal, nullptr, "%s\n", message);
fatalWithMessage(message);
}
}

void assertFatalWithNode(
const YGNodeConstRef node,
const yoga::Node* const node,
const bool condition,
const char* message) {
if (!condition) {
yoga::log(
// TODO: Break log callbacks and make them const correct
static_cast<yoga::Node*>(const_cast<YGNodeRef>(node)),
YGLogLevelFatal,
nullptr,
"%s\n",
message);
yoga::log(node, YGLogLevelFatal, nullptr, "%s\n", message);
fatalWithMessage(message);
}
}

void assertFatalWithConfig(
YGConfigRef config,
const yoga::Config* const config,
const bool condition,
const char* message) {
if (!condition) {
yoga::log(
static_cast<yoga::Config*>(config),
YGLogLevelFatal,
nullptr,
"%s\n",
message);
yoga::log(config, YGLogLevelFatal, nullptr, "%s\n", message);
fatalWithMessage(message);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ namespace facebook::yoga {

void assertFatal(bool condition, const char* message);
void assertFatalWithNode(
YGNodeConstRef node,
const yoga::Node* node,
bool condition,
const char* message);
void assertFatalWithConfig(
YGConfigRef config,
const yoga::Config* config,
bool condition,
const char* message);

Expand Down
23 changes: 15 additions & 8 deletions packages/react-native/ReactCommon/yoga/yoga/debug/Log.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,28 @@ namespace facebook::yoga {
namespace {

void vlog(
yoga::Config* config,
yoga::Node* node,
const yoga::Config* config,
const yoga::Node* node,
YGLogLevel level,
void* context,
const char* format,
va_list args) {
yoga::Config* logConfig = config != nullptr
? config
: static_cast<yoga::Config*>(YGConfigGetDefault());
logConfig->log(node, level, context, format, args);
const yoga::Config* logConfig =
config != nullptr ? config : resolveRef(YGConfigGetDefault());

logConfig->log(const_cast<yoga::Node*>(node), level, context, format, args);
}
} // namespace

void log(YGLogLevel level, void* context, const char* format, ...) noexcept {
va_list args;
va_start(args, format);
vlog(nullptr, nullptr, level, context, format, args);
va_end(args);
}

void log(
yoga::Node* node,
const yoga::Node* node,
YGLogLevel level,
void* context,
const char* format,
Expand All @@ -44,7 +51,7 @@ void log(
}

void log(
yoga::Config* config,
const yoga::Config* config,
YGLogLevel level,
void* context,
const char* format,
Expand Down
6 changes: 4 additions & 2 deletions packages/react-native/ReactCommon/yoga/yoga/debug/Log.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,17 @@

namespace facebook::yoga {

void log(YGLogLevel level, void*, const char* format, ...) noexcept;

void log(
yoga::Node* node,
const yoga::Node* node,
YGLogLevel level,
void*,
const char* message,
...) noexcept;

void log(
yoga::Config* config,
const yoga::Config* config,
YGLogLevel level,
void*,
const char* format,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ static void appendEdgeIfNotUndefined(

void nodeToString(
std::string& str,
yoga::Node* node,
const yoga::Node* node,
YGPrintOptions options,
uint32_t level) {
indent(str, level);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace facebook::yoga {

void nodeToString(
std::string& str,
yoga::Node* node,
const yoga::Node* node,
YGPrintOptions options,
uint32_t level);

Expand Down
9 changes: 8 additions & 1 deletion packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,14 @@ YOGA_EXPORT void Node::clearChildren() {
// Other Methods

void Node::cloneChildrenIfNeeded(void* cloneContext) {
iterChildrenAfterCloningIfNeeded([](Node*, void*) {}, cloneContext);
int i = 0;
for (Node*& child : children_) {
if (child->getOwner() != this) {
child = resolveRef(config_->cloneNode(child, this, i, cloneContext));
child->setOwner(this);
}
i += 1;
}
}

void Node::markDirtyAndPropagate() {
Expand Down
Loading

0 comments on commit cacb81d

Please sign in to comment.