Breaking: YGConfigRef related const-correctness fixes (#1371)
Summary: X-link: https://github.com/facebook/react-native/pull/39374 Pull Request resolved: https://github.com/facebook/yoga/pull/1371 Right now `YGConfigGetDefault` and `YGNodeGetConfig` both return mutable, freeable, configs, which is bad, since the former points to a global singleton config, and the latter usually does too. Mutating this is not thread safe, and it should never be freed. This change makes these functions return `YGConfigConstRef` to prevent mutation, and also lets us allow `YGConfigNewWithConfig` to accept a const config. If a caller does want to mutate a config (such as to free it), it must be tracked manually. Changelog: [Internal] Reviewed By: javache Differential Revision: D49132476 fbshipit-source-id: ac9ce61149e69c6c25cadb99711435b0a5b9f38a
This commit is contained in:
committed by
Facebook GitHub Bot
parent
a003c09a4c
commit
0720e0b22a
@@ -32,7 +32,7 @@ YOGA_EXPORT void YGNodeSetContext(YGNodeRef node, void* context) {
|
|||||||
return resolveRef(node)->setContext(context);
|
return resolveRef(node)->setContext(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
YOGA_EXPORT YGConfigRef YGNodeGetConfig(YGNodeRef node) {
|
YOGA_EXPORT YGConfigConstRef YGNodeGetConfig(YGNodeRef node) {
|
||||||
return resolveRef(node)->getConfig();
|
return resolveRef(node)->getConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,22 +103,18 @@ YOGA_EXPORT void YGNodeMarkDirtyAndPropagateToDescendants(
|
|||||||
return resolveRef(node)->markDirtyAndPropagateDownwards();
|
return resolveRef(node)->markDirtyAndPropagateDownwards();
|
||||||
}
|
}
|
||||||
|
|
||||||
YOGA_EXPORT WIN_EXPORT YGNodeRef YGNodeNewWithConfig(const YGConfigRef config) {
|
YOGA_EXPORT WIN_EXPORT YGNodeRef
|
||||||
|
YGNodeNewWithConfig(const YGConfigConstRef config) {
|
||||||
auto* node = new yoga::Node{resolveRef(config)};
|
auto* node = new yoga::Node{resolveRef(config)};
|
||||||
yoga::assertFatal(
|
yoga::assertFatal(
|
||||||
config != nullptr, "Tried to construct YGNode with null config");
|
config != nullptr, "Tried to construct YGNode with null config");
|
||||||
yoga::assertFatalWithConfig(
|
|
||||||
resolveRef(config),
|
|
||||||
node != nullptr,
|
|
||||||
"Could not allocate memory for node");
|
|
||||||
Event::publish<Event::NodeAllocation>(node, {config});
|
Event::publish<Event::NodeAllocation>(node, {config});
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
YOGA_EXPORT YGConfigRef YGConfigGetDefault() {
|
YOGA_EXPORT YGConfigConstRef YGConfigGetDefault() {
|
||||||
static YGConfigRef defaultConfig = YGConfigNew();
|
return &yoga::Config::getDefault();
|
||||||
return defaultConfig;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
YOGA_EXPORT YGNodeRef YGNodeNew(void) {
|
YOGA_EXPORT YGNodeRef YGNodeNew(void) {
|
||||||
|
@@ -52,7 +52,7 @@ typedef YGNodeRef (*YGCloneNodeFunc)(
|
|||||||
|
|
||||||
// YGNode
|
// YGNode
|
||||||
WIN_EXPORT YGNodeRef YGNodeNew(void);
|
WIN_EXPORT YGNodeRef YGNodeNew(void);
|
||||||
WIN_EXPORT YGNodeRef YGNodeNewWithConfig(YGConfigRef config);
|
WIN_EXPORT YGNodeRef YGNodeNewWithConfig(YGConfigConstRef config);
|
||||||
WIN_EXPORT YGNodeRef YGNodeClone(YGNodeConstRef node);
|
WIN_EXPORT YGNodeRef YGNodeClone(YGNodeConstRef node);
|
||||||
WIN_EXPORT void YGNodeFree(YGNodeRef node);
|
WIN_EXPORT void YGNodeFree(YGNodeRef node);
|
||||||
WIN_EXPORT void YGNodeFreeRecursiveWithCleanupFunc(
|
WIN_EXPORT void YGNodeFreeRecursiveWithCleanupFunc(
|
||||||
@@ -131,7 +131,7 @@ WIN_EXPORT void YGNodeCopyStyle(YGNodeRef dstNode, YGNodeConstRef srcNode);
|
|||||||
WIN_EXPORT void* YGNodeGetContext(YGNodeConstRef node);
|
WIN_EXPORT void* YGNodeGetContext(YGNodeConstRef node);
|
||||||
WIN_EXPORT void YGNodeSetContext(YGNodeRef node, void* context);
|
WIN_EXPORT void YGNodeSetContext(YGNodeRef node, void* context);
|
||||||
|
|
||||||
WIN_EXPORT YGConfigRef YGNodeGetConfig(YGNodeRef node);
|
WIN_EXPORT YGConfigConstRef YGNodeGetConfig(YGNodeRef node);
|
||||||
WIN_EXPORT void YGNodeSetConfig(YGNodeRef node, YGConfigRef config);
|
WIN_EXPORT void YGNodeSetConfig(YGNodeRef node, YGConfigRef config);
|
||||||
|
|
||||||
void YGConfigSetPrintTreeFlag(YGConfigRef config, bool enabled);
|
void YGConfigSetPrintTreeFlag(YGConfigRef config, bool enabled);
|
||||||
@@ -327,7 +327,7 @@ WIN_EXPORT void YGConfigSetCloneNodeFunc(
|
|||||||
YGConfigRef config,
|
YGConfigRef config,
|
||||||
YGCloneNodeFunc callback);
|
YGCloneNodeFunc callback);
|
||||||
|
|
||||||
WIN_EXPORT YGConfigRef YGConfigGetDefault(void);
|
WIN_EXPORT YGConfigConstRef YGConfigGetDefault(void);
|
||||||
|
|
||||||
WIN_EXPORT void YGConfigSetContext(YGConfigRef config, void* context);
|
WIN_EXPORT void YGConfigSetContext(YGConfigRef config, void* context);
|
||||||
WIN_EXPORT void* YGConfigGetContext(YGConfigConstRef config);
|
WIN_EXPORT void* YGConfigGetContext(YGConfigConstRef config);
|
||||||
|
@@ -6,15 +6,18 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <yoga/config/Config.h>
|
#include <yoga/config/Config.h>
|
||||||
|
#include <yoga/debug/Log.h>
|
||||||
#include <yoga/node/Node.h>
|
#include <yoga/node/Node.h>
|
||||||
|
|
||||||
namespace facebook::yoga {
|
namespace facebook::yoga {
|
||||||
|
|
||||||
bool configUpdateInvalidatesLayout(Config* a, Config* b) {
|
bool configUpdateInvalidatesLayout(
|
||||||
return a->getErrata() != b->getErrata() ||
|
const Config& oldConfig,
|
||||||
a->getEnabledExperiments() != b->getEnabledExperiments() ||
|
const Config& newConfig) {
|
||||||
a->getPointScaleFactor() != b->getPointScaleFactor() ||
|
return oldConfig.getErrata() != newConfig.getErrata() ||
|
||||||
a->useWebDefaults() != b->useWebDefaults();
|
oldConfig.getEnabledExperiments() != newConfig.getEnabledExperiments() ||
|
||||||
|
oldConfig.getPointScaleFactor() != newConfig.getPointScaleFactor() ||
|
||||||
|
oldConfig.useWebDefaults() != newConfig.useWebDefaults();
|
||||||
}
|
}
|
||||||
|
|
||||||
Config::Config(YGLogger logger) : cloneNodeCallback_{nullptr} {
|
Config::Config(YGLogger logger) : cloneNodeCallback_{nullptr} {
|
||||||
@@ -145,4 +148,9 @@ YGNodeRef Config::cloneNode(
|
|||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*static*/ const Config& Config::getDefault() {
|
||||||
|
static Config config{getDefaultLogger()};
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace facebook::yoga
|
} // namespace facebook::yoga
|
||||||
|
@@ -18,9 +18,11 @@ namespace facebook::yoga {
|
|||||||
class Config;
|
class Config;
|
||||||
class Node;
|
class Node;
|
||||||
|
|
||||||
// Whether moving a node from config "a" to config "b" should dirty previously
|
// Whether moving a node from an old to new config should dirty previously
|
||||||
// calculated layout results.
|
// calculated layout results.
|
||||||
bool configUpdateInvalidatesLayout(Config* a, Config* b);
|
bool configUpdateInvalidatesLayout(
|
||||||
|
const Config& oldConfig,
|
||||||
|
const Config& newConfig);
|
||||||
|
|
||||||
// Internal variants of log functions, currently used only by JNI bindings.
|
// Internal variants of log functions, currently used only by JNI bindings.
|
||||||
// TODO: Reconcile this with the public API
|
// TODO: Reconcile this with the public API
|
||||||
@@ -95,6 +97,8 @@ public:
|
|||||||
size_t childIndex,
|
size_t childIndex,
|
||||||
void* cloneContext) const;
|
void* cloneContext) const;
|
||||||
|
|
||||||
|
static const Config& getDefault();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
union {
|
union {
|
||||||
CloneWithContextFn withContext;
|
CloneWithContextFn withContext;
|
||||||
|
@@ -22,10 +22,11 @@ void vlog(
|
|||||||
void* context,
|
void* context,
|
||||||
const char* format,
|
const char* format,
|
||||||
va_list args) {
|
va_list args) {
|
||||||
const yoga::Config* logConfig =
|
if (config == nullptr) {
|
||||||
config != nullptr ? config : resolveRef(YGConfigGetDefault());
|
getDefaultLogger()(nullptr, node, level, format, args);
|
||||||
|
} else {
|
||||||
logConfig->log(const_cast<yoga::Node*>(node), level, context, format, args);
|
config->log(node, level, context, format, args);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@@ -95,12 +95,12 @@ private:
|
|||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct Event::TypedData<Event::NodeAllocation> {
|
struct Event::TypedData<Event::NodeAllocation> {
|
||||||
YGConfigRef config;
|
YGConfigConstRef config;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct Event::TypedData<Event::NodeDeallocation> {
|
struct Event::TypedData<Event::NodeDeallocation> {
|
||||||
YGConfigRef config;
|
YGConfigConstRef config;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
@@ -17,7 +17,9 @@
|
|||||||
|
|
||||||
namespace facebook::yoga {
|
namespace facebook::yoga {
|
||||||
|
|
||||||
Node::Node(yoga::Config* config) : config_{config} {
|
Node::Node() : Node{&Config::getDefault()} {}
|
||||||
|
|
||||||
|
Node::Node(const yoga::Config* config) : config_{config} {
|
||||||
yoga::assertFatal(
|
yoga::assertFatal(
|
||||||
config != nullptr, "Attempting to construct Node with null config");
|
config != nullptr, "Attempting to construct Node with null config");
|
||||||
|
|
||||||
@@ -285,7 +287,7 @@ void Node::setConfig(yoga::Config* config) {
|
|||||||
config->useWebDefaults() == config_->useWebDefaults(),
|
config->useWebDefaults() == config_->useWebDefaults(),
|
||||||
"UseWebDefaults may not be changed after constructing a Node");
|
"UseWebDefaults may not be changed after constructing a Node");
|
||||||
|
|
||||||
if (yoga::configUpdateInvalidatesLayout(config_, config)) {
|
if (yoga::configUpdateInvalidatesLayout(*config_, *config)) {
|
||||||
markDirtyAndPropagate();
|
markDirtyAndPropagate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -71,7 +71,7 @@ private:
|
|||||||
size_t lineIndex_ = 0;
|
size_t lineIndex_ = 0;
|
||||||
Node* owner_ = nullptr;
|
Node* owner_ = nullptr;
|
||||||
std::vector<Node*> children_ = {};
|
std::vector<Node*> children_ = {};
|
||||||
Config* config_;
|
const Config* config_;
|
||||||
std::array<YGValue, 2> resolvedDimensions_ = {
|
std::array<YGValue, 2> resolvedDimensions_ = {
|
||||||
{YGValueUndefined, YGValueUndefined}};
|
{YGValueUndefined, YGValueUndefined}};
|
||||||
|
|
||||||
@@ -95,10 +95,8 @@ private:
|
|||||||
Node& operator=(Node&&) = default;
|
Node& operator=(Node&&) = default;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Node() : Node{static_cast<Config*>(YGConfigGetDefault())} {
|
Node();
|
||||||
flags_.hasNewLayout = true;
|
explicit Node(const Config* config);
|
||||||
}
|
|
||||||
explicit Node(Config* config);
|
|
||||||
~Node() = default; // cleanup of owner/children relationships in YGNodeFree
|
~Node() = default; // cleanup of owner/children relationships in YGNodeFree
|
||||||
|
|
||||||
Node(Node&&);
|
Node(Node&&);
|
||||||
@@ -165,7 +163,7 @@ public:
|
|||||||
|
|
||||||
size_t getChildCount() const { return children_.size(); }
|
size_t getChildCount() const { return children_.size(); }
|
||||||
|
|
||||||
Config* getConfig() const { return config_; }
|
const Config* getConfig() const { return config_; }
|
||||||
|
|
||||||
bool isDirty() const { return flags_.isDirty; }
|
bool isDirty() const { return flags_.isDirty; }
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user