Skip to content

Commit

Permalink
Add YGErrata Enum (#1256)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: #1256

X-link: facebook/react-native#37076

This adds a `YGErrata` bitset enum matching the API and guarantees described in #1247.

It is hooked up in later diffs. There are a couple of `YGExperimentalFeature` values that belong here, but keeping the current options means that the default `YGErrataNone` corresponds to existing default behavior, letting us stage the series of changes as:
1. Implement errata API
2. Update internal Yoga users we want to de-risk to `YGErrataClassic` or `YGErrataAll` (if setting `UseLegacyStretchBehaviour`)
3. Add new errata, changing Yoga defaults to be conformant, while letting internal apps opt into compatibility modes pending experimentation.

I also added a macro to let C++ users of Yoga perform bitwise operations on the enum without casting (already available for C users).

Reviewed By: rshest

Differential Revision: D45254098

fbshipit-source-id: 287b12f8df38e0735dea102b3437ab89cbca3d22
  • Loading branch information
NickGerleman authored and facebook-github-bot committed Apr 25, 2023
1 parent b15894b commit da9265b
Show file tree
Hide file tree
Showing 8 changed files with 166 additions and 0 deletions.
20 changes: 20 additions & 0 deletions csharp/Facebook.Yoga/YogaErrata.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* 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.
*/

// @generated by enums.py

namespace Facebook.Yoga
{
[System.Flags]
public enum YogaErrata
{
None = 0,
StretchFlexBasis = 1,
All = 2147483647,
Classic = 2147483646,
}
}
17 changes: 17 additions & 0 deletions enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,28 @@
],
"PrintOptions": [("Layout", 1), ("Style", 2), ("Children", 4)],
"Gutter": ["Column", "Row", "All"],
# Known incorrect behavior which can be enabled for compatibility
"Errata": [
# Default: Standards conformant mode
("None", 0),
# Allows main-axis flex basis to be stretched without flexGrow being
# set (previously referred to as "UseLegacyStretchBehaviour")
("StretchFlexBasis", 1 << 0),
# Enable all incorrect behavior (preserve compatibility)
("All", 0x7FFFFFFF),
# Enable all errata except for "StretchFlexBasis" (Defaults behavior
# before Yoga 2.0)
("Classic", 0x7FFFFFFF & (~(1 << 0))),
],
}

# Generated Java enums used to emit @DoNotStrip, but D17519844 removed them
# manually from all but YogaLogLevel. TODO: Is it safe to remove from it as
# well?
DO_NOT_STRIP = ["LogLevel"]

BITSET_ENUMS = ["Errata"]


def get_license(ext):
prologue = "/**" if ext == "js" else "/*"
Expand Down Expand Up @@ -132,6 +147,8 @@ def to_log_lower(symbol):
f.write(")\n")
else:
f.write(",\n")
if name in BITSET_ENUMS:
f.write("YG_DEFINE_ENUM_FLAG_OPERATORS(YG%s)\n" % name)
f.write("\n")
f.write("YG_EXTERN_C_END\n")

Expand Down
37 changes: 37 additions & 0 deletions java/com/facebook/yoga/YogaErrata.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* 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.
*/

// @generated by enums.py

package com.facebook.yoga;

public enum YogaErrata {
NONE(0),
STRETCH_FLEX_BASIS(1),
ALL(2147483647),
CLASSIC(2147483646);

private final int mIntValue;

YogaErrata(int intValue) {
mIntValue = intValue;
}

public int intValue() {
return mIntValue;
}

public static YogaErrata fromInt(int value) {
switch (value) {
case 0: return NONE;
case 1: return STRETCH_FLEX_BASIS;
case 2147483647: return ALL;
case 2147483646: return CLASSIC;
default: throw new IllegalArgumentException("Unknown enum value: " + value);
}
}
}
19 changes: 19 additions & 0 deletions javascript/src_js/generated/YGEnums.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,19 @@ type EDGE_ALL = 8 & ['EDGE']
export const EDGE_ALL: EDGE_ALL;


type ERRATA_NONE = 0 & ['ERRATA']
export const ERRATA_NONE: ERRATA_NONE;

type ERRATA_STRETCH_FLEX_BASIS = 1 & ['ERRATA']
export const ERRATA_STRETCH_FLEX_BASIS: ERRATA_STRETCH_FLEX_BASIS;

type ERRATA_ALL = 2147483647 & ['ERRATA']
export const ERRATA_ALL: ERRATA_ALL;

type ERRATA_CLASSIC = 2147483646 & ['ERRATA']
export const ERRATA_CLASSIC: ERRATA_CLASSIC;


type EXPERIMENTAL_FEATURE_WEB_FLEX_BASIS = 0 & ['EXPERIMENTAL_FEATURE']
export const EXPERIMENTAL_FEATURE_WEB_FLEX_BASIS: EXPERIMENTAL_FEATURE_WEB_FLEX_BASIS;

Expand Down Expand Up @@ -259,6 +272,12 @@ export type Edge =
| typeof EDGE_VERTICAL
| typeof EDGE_ALL;

export type Errata =
| typeof ERRATA_NONE
| typeof ERRATA_STRETCH_FLEX_BASIS
| typeof ERRATA_ALL
| typeof ERRATA_CLASSIC;

export type ExperimentalFeature =
| typeof EXPERIMENTAL_FEATURE_WEB_FLEX_BASIS
| typeof EXPERIMENTAL_FEATURE_ABSOLUTE_PERCENTAGE_AGAINST_PADDING_EDGE
Expand Down
5 changes: 5 additions & 0 deletions javascript/src_js/generated/YGEnums.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ exports.EDGE_HORIZONTAL = 6;
exports.EDGE_VERTICAL = 7;
exports.EDGE_ALL = 8;

exports.ERRATA_NONE = 0;
exports.ERRATA_STRETCH_FLEX_BASIS = 1;
exports.ERRATA_ALL = 2147483647;
exports.ERRATA_CLASSIC = 2147483646;

exports.EXPERIMENTAL_FEATURE_WEB_FLEX_BASIS = 0;
exports.EXPERIMENTAL_FEATURE_ABSOLUTE_PERCENTAGE_AGAINST_PADDING_EDGE = 1;
exports.EXPERIMENTAL_FEATURE_FIX_ABSOLUTE_TRAILING_COLUMN_MARGIN = 2;
Expand Down
14 changes: 14 additions & 0 deletions yoga/YGEnums.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,20 @@ const char* YGEdgeToString(const YGEdge value) {
return "unknown";
}

const char* YGErrataToString(const YGErrata value) {
switch (value) {
case YGErrataNone:
return "none";
case YGErrataStretchFlexBasis:
return "stretch-flex-basis";
case YGErrataAll:
return "all";
case YGErrataClassic:
return "classic";
}
return "unknown";
}

const char* YGExperimentalFeatureToString(const YGExperimentalFeature value) {
switch (value) {
case YGExperimentalFeatureWebFlexBasis:
Expand Down
8 changes: 8 additions & 0 deletions yoga/YGEnums.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ YG_ENUM_SEQ_DECL(
YGEdgeVertical,
YGEdgeAll)

YG_ENUM_DECL(
YGErrata,
YGErrataNone = 0,
YGErrataStretchFlexBasis = 1,
YGErrataAll = 2147483647,
YGErrataClassic = 2147483646)
YG_DEFINE_ENUM_FLAG_OPERATORS(YGErrata)

YG_ENUM_SEQ_DECL(
YGExperimentalFeature,
YGExperimentalFeatureWebFlexBasis,
Expand Down
46 changes: 46 additions & 0 deletions yoga/YGMacros.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@

#pragma once

#ifdef __cplusplus
#include <type_traits>
#endif

#ifdef __cplusplus
#define YG_EXTERN_C_BEGIN extern "C" {
#define YG_EXTERN_C_END }
Expand Down Expand Up @@ -40,6 +44,48 @@
#define YG_ENUM_END(name) name
#endif

#ifdef __cplusplus
#define YG_DEFINE_ENUM_FLAG_OPERATORS(name) \
extern "C++" { \
constexpr inline name operator~(name a) { \
return static_cast<name>( \
~static_cast<std::underlying_type<name>::type>(a)); \
} \
constexpr inline name operator|(name a, name b) { \
return static_cast<name>( \
static_cast<std::underlying_type<name>::type>(a) | \
static_cast<std::underlying_type<name>::type>(b)); \
} \
constexpr inline name operator&(name a, name b) { \
return static_cast<name>( \
static_cast<std::underlying_type<name>::type>(a) & \
static_cast<std::underlying_type<name>::type>(b)); \
} \
constexpr inline name operator^(name a, name b) { \
return static_cast<name>( \
static_cast<std::underlying_type<name>::type>(a) ^ \
static_cast<std::underlying_type<name>::type>(b)); \
} \
inline name& operator|=(name& a, name b) { \
return reinterpret_cast<name&>( \
reinterpret_cast<std::underlying_type<name>::type&>(a) |= \
static_cast<std::underlying_type<name>::type>(b)); \
} \
inline name& operator&=(name& a, name b) { \
return reinterpret_cast<name&>( \
reinterpret_cast<std::underlying_type<name>::type&>(a) &= \
static_cast<std::underlying_type<name>::type>(b)); \
} \
inline name& operator^=(name& a, name b) { \
return reinterpret_cast<name&>( \
reinterpret_cast<std::underlying_type<name>::type&>(a) ^= \
static_cast<std::underlying_type<name>::type>(b)); \
} \
}
#else
#define YG_DEFINE_ENUM_FLAG_OPERATORS(name)
#endif

#ifdef __cplusplus
namespace facebook {
namespace yoga {
Expand Down

0 comments on commit da9265b

Please sign in to comment.