diff --git a/engine/src/flutter/shell/platform/embedder/embedder.h b/engine/src/flutter/shell/platform/embedder/embedder.h index 60a90f45f94..989b9cce6be 100644 --- a/engine/src/flutter/shell/platform/embedder/embedder.h +++ b/engine/src/flutter/shell/platform/embedder/embedder.h @@ -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. diff --git a/engine/src/flutter/shell/platform/embedder/tests/embedder_frozen.h b/engine/src/flutter/shell/platform/embedder/tests/embedder_frozen.h index 46e00f07845..60c995fed61 100644 --- a/engine/src/flutter/shell/platform/embedder/tests/embedder_frozen.h +++ b/engine/src/flutter/shell/platform/embedder/tests/embedder_frozen.h @@ -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; diff --git a/engine/src/flutter/shell/platform/embedder/tests/embedder_frozen_unittests.cc b/engine/src/flutter/shell/platform/embedder/tests/embedder_frozen_unittests.cc index eb173fe3519..4235547e831 100644 --- a/engine/src/flutter/shell/platform/embedder/tests/embedder_frozen_unittests.cc +++ b/engine/src/flutter/shell/platform/embedder/tests/embedder_frozen_unittests.cc @@ -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