mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[Embedder API] Lock nested structs to guarantee ABI (flutter/engine#40069)
[Embedder API] Lock nested structs for ABI stability
This commit is contained in:
parent
c9d003f7b3
commit
89a738d1b7
@ -25,12 +25,16 @@
|
||||
// - Function signatures (names, argument counts, argument order, and argument
|
||||
// type) cannot change.
|
||||
// - The core behavior of existing functions cannot change.
|
||||
// - Instead of nesting structures by value within another structure, prefer
|
||||
// nesting by pointer. This ensures that adding members to the nested struct
|
||||
// does not break the ABI of the parent struct.
|
||||
// - Instead of array of structures, prefer array of pointers to structures.
|
||||
// This ensures that array indexing does not break if members are added
|
||||
// to the structure.
|
||||
//
|
||||
// These changes are allowed:
|
||||
// - Adding new struct members at the end of a structure.
|
||||
// - Adding new struct members at the end of a structure as long as the struct
|
||||
// is not nested within another struct by value.
|
||||
// - Adding new enum members with a new value.
|
||||
// - Renaming a struct member as long as its type, size, and intent remain the
|
||||
// same.
|
||||
|
||||
@ -22,6 +22,47 @@
|
||||
namespace flutter {
|
||||
namespace testing {
|
||||
|
||||
// New members must not be added to `FlutterTransformation`
|
||||
// as it would break the ABI of `FlutterSemanticsNode`.
|
||||
// See: https://github.com/flutter/flutter/issues/121176
|
||||
typedef struct {
|
||||
double scaleX;
|
||||
double skewX;
|
||||
double transX;
|
||||
double skewY;
|
||||
double scaleY;
|
||||
double transY;
|
||||
double pers0;
|
||||
double pers1;
|
||||
double pers2;
|
||||
} FrozenFlutterTransformation;
|
||||
|
||||
// New members must not be added to `FlutterRect` as it would
|
||||
// break the ABI of `FlutterSemanticsNode` and `FlutterDamage`.
|
||||
// See: https://github.com/flutter/flutter/issues/121176
|
||||
// See: https://github.com/flutter/flutter/issues/121347
|
||||
typedef struct {
|
||||
double left;
|
||||
double top;
|
||||
double right;
|
||||
double bottom;
|
||||
} FrozenFlutterRect;
|
||||
|
||||
// New members must not be added to `FlutterPoint` as it would
|
||||
// break the ABI of `FlutterLayer`.
|
||||
typedef struct {
|
||||
double x;
|
||||
double y;
|
||||
} FrozenFlutterPoint;
|
||||
|
||||
// New members must not be added to `FlutterDamage` as it would
|
||||
// break the ABI of `FlutterPresentInfo`.
|
||||
typedef struct {
|
||||
size_t struct_size;
|
||||
size_t num_rects;
|
||||
FrozenFlutterRect* damage;
|
||||
} FrozenFlutterDamage;
|
||||
|
||||
// New members must not be added to `FlutterSemanticsNode`
|
||||
// as it would break the ABI of `FlutterSemanticsUpdate`.
|
||||
// See: https://github.com/flutter/flutter/issues/121176
|
||||
@ -45,8 +86,8 @@ typedef struct {
|
||||
const char* increased_value;
|
||||
const char* decreased_value;
|
||||
FlutterTextDirection text_direction;
|
||||
FlutterRect rect;
|
||||
FlutterTransformation transform;
|
||||
FrozenFlutterRect rect;
|
||||
FrozenFlutterTransformation transform;
|
||||
size_t child_count;
|
||||
const int32_t* children_in_traversal_order;
|
||||
const int32_t* children_in_hit_test_order;
|
||||
|
||||
@ -14,6 +14,47 @@ namespace testing {
|
||||
#define ASSERT_EQ_OFFSET(type1, type2, member) \
|
||||
ASSERT_EQ(offsetof(type1, member), offsetof(type2, member))
|
||||
|
||||
// New members must not be added to `FlutterTransformation`
|
||||
// as it would break the ABI of `FlutterSemanticsNode`.
|
||||
// See: https://github.com/flutter/flutter/issues/121176
|
||||
TEST(EmbedderFrozen, FlutterTransformationIsFrozen) {
|
||||
ASSERT_EQ_OFFSET(FlutterTransformation, FrozenFlutterTransformation, scaleX);
|
||||
ASSERT_EQ_OFFSET(FlutterTransformation, FrozenFlutterTransformation, skewX);
|
||||
ASSERT_EQ_OFFSET(FlutterTransformation, FrozenFlutterTransformation, transX);
|
||||
ASSERT_EQ_OFFSET(FlutterTransformation, FrozenFlutterTransformation, skewY);
|
||||
ASSERT_EQ_OFFSET(FlutterTransformation, FrozenFlutterTransformation, scaleY);
|
||||
ASSERT_EQ_OFFSET(FlutterTransformation, FrozenFlutterTransformation, transY);
|
||||
ASSERT_EQ_OFFSET(FlutterTransformation, FrozenFlutterTransformation, pers0);
|
||||
ASSERT_EQ_OFFSET(FlutterTransformation, FrozenFlutterTransformation, pers1);
|
||||
ASSERT_EQ_OFFSET(FlutterTransformation, FrozenFlutterTransformation, pers2);
|
||||
}
|
||||
|
||||
// New members must not be added to `FlutterRect` as it would
|
||||
// break the ABI of `FlutterSemanticsNode` and `FlutterDamage`.
|
||||
// See: https://github.com/flutter/flutter/issues/121176
|
||||
// See: https://github.com/flutter/flutter/issues/121347
|
||||
TEST(EmbedderFrozen, FlutterRectIsFrozen) {
|
||||
ASSERT_EQ_OFFSET(FlutterRect, FrozenFlutterRect, left);
|
||||
ASSERT_EQ_OFFSET(FlutterRect, FrozenFlutterRect, top);
|
||||
ASSERT_EQ_OFFSET(FlutterRect, FrozenFlutterRect, right);
|
||||
ASSERT_EQ_OFFSET(FlutterRect, FrozenFlutterRect, bottom);
|
||||
}
|
||||
|
||||
// New members must not be added to `FlutterPoint` as it would
|
||||
// break the ABI of `FlutterLayer`.
|
||||
TEST(EmbedderFrozen, FlutterPointIsFrozen) {
|
||||
ASSERT_EQ_OFFSET(FlutterPoint, FrozenFlutterPoint, x);
|
||||
ASSERT_EQ_OFFSET(FlutterPoint, FrozenFlutterPoint, y);
|
||||
}
|
||||
|
||||
// New members must not be added to `FlutterDamage` as it would
|
||||
// break the ABI of `FlutterPresentInfo`.
|
||||
TEST(EmbedderFrozen, FlutterDamageIsFrozen) {
|
||||
ASSERT_EQ_OFFSET(FlutterDamage, FrozenFlutterDamage, struct_size);
|
||||
ASSERT_EQ_OFFSET(FlutterDamage, FrozenFlutterDamage, num_rects);
|
||||
ASSERT_EQ_OFFSET(FlutterDamage, FrozenFlutterDamage, damage);
|
||||
}
|
||||
|
||||
// New members must not be added to `FlutterSemanticsNode`
|
||||
// as it would break the ABI of `FlutterSemanticsUpdate`.
|
||||
// See: https://github.com/flutter/flutter/issues/121176
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user