expo-modules-core 58.0.9 → 58.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 58.0.10
4
+
5
+ ### Patch Changes
6
+
7
+ - Lay out `RNHostView` hosted content at the size SwiftUI or Compose gives it on an axis that `matchContents` does not match. ([#50674](https://github.com/expo/expo/pull/50674) by [@intergalacticspacehighway](https://github.com/intergalacticspacehighway))
8
+ - Updated dependencies. ([#50805](https://github.com/expo/expo/pull/50805), [#50844](https://github.com/expo/expo/pull/50844), [#50806](https://github.com/expo/expo/pull/50806))
9
+ - expo-modules-jsi@58.0.6
10
+
3
11
  ## 58.0.9
4
12
 
5
13
  ### Patch Changes
@@ -20,7 +28,7 @@
20
28
 
21
29
  ### 🐛 Bug fixes
22
30
 
23
- - Fixed listeners removed with `subscription.remove()` never being garbage-collected, together with their emitter and everything their closure references, when the closure can reach the subscription (as in `useEvent`, `useEventListener` or a `useEffect` that returns `() => subscription.remove()`).
31
+ - Fixed listeners removed with `subscription.remove()` never being garbage-collected, together with their emitter and everything their closure references, when the closure can reach the subscription (as in `useEvent`, `useEventListener` or a `useEffect` that returns `() => subscription.remove()`). ([#50603](https://github.com/expo/expo/pull/50603) by [@gkueny](https://github.com/gkueny))
24
32
  - [iOS] Fixed `Exception` reporting `undefined reason` to JavaScript instead of the description it was created with, which also affected every `promise.reject(code, description)` call. ([#50215](https://github.com/expo/expo/pull/50215) by [@Maher-Reven](https://github.com/Maher-Reven))
25
33
 
26
34
  ## 58.0.6 — 2026-09-23
@@ -46,7 +46,7 @@ if (shouldIncludeCompose) {
46
46
  }
47
47
 
48
48
  group = 'host.exp.exponent'
49
- version = '58.0.9'
49
+ version = '58.0.10'
50
50
 
51
51
  def isExpoModulesCoreTests = {
52
52
  Gradle gradle = getGradle()
@@ -175,7 +175,7 @@ android {
175
175
  defaultConfig {
176
176
  consumerProguardFiles 'proguard-rules.pro'
177
177
  versionCode 1
178
- versionName "58.0.9"
178
+ versionName "58.0.10"
179
179
  buildConfigField "String", "EXPO_MODULES_CORE_VERSION", "\"${versionName}\""
180
180
  buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", "true"
181
181
 
@@ -2,6 +2,7 @@ package expo.modules.kotlin.types.worklets
2
2
 
3
3
  import expo.modules.kotlin.jni.CppType
4
4
  import expo.modules.kotlin.jni.ExpectedType
5
+ import expo.modules.kotlin.jni.WorkletsSoLoader
5
6
  import expo.modules.kotlin.jni.worklets.Serializable
6
7
  import expo.modules.kotlin.types.ConverterContext
7
8
  import expo.modules.kotlin.types.NonNullableTypeConverter
@@ -12,6 +13,9 @@ class SerializableTypeConverter : NonNullableTypeConverter<Serializable>() {
12
13
  }
13
14
 
14
15
  override fun getCppRequiredTypes(): ExpectedType {
16
+ // Register the C++ converter before a function caches its argument converters.
17
+ // Module functions can be exported before the UI worklet runtime is installed.
18
+ WorkletsSoLoader.loadIfPresent()
15
19
  return ExpectedType(CppType.SERIALIZABLE)
16
20
  }
17
21
 
@@ -61,17 +61,47 @@ public:
61
61
 
62
62
  const auto snode = dynamic_cast<ShadowNodeType *>(&shadowNode);
63
63
  const auto state = snode->getStateData();
64
+ auto const &sharedProps = snode->getProps();
65
+ auto &style = const_cast<facebook::yoga::Style &>(
66
+ static_cast<const facebook::react::ViewProps &>(*sharedProps).yogaStyle);
67
+ bool propsStyleChanged = false;
64
68
 
69
+ if (isRNHostView(sharedProps)) {
70
+ // If RNHostView has align self set to auto or stretch, we should override it to flex-start so that the node can size itself to its content
71
+ auto const alignSelf = style.alignSelf();
72
+
73
+ if (alignSelf == facebook::yoga::Align::Auto || alignSelf == facebook::yoga::Align::Stretch) {
74
+ style.setAlignSelf(facebook::yoga::Align::FlexStart);
75
+ propsStyleChanged = true;
76
+ }
77
+ }
78
+
79
+ // handle layout style prop update
80
+ if (!isnan(state._styleWidth)) {
81
+ style.setDimension(facebook::yoga::Dimension::Width,
82
+ facebook::yoga::StyleSizeLength::points(state._styleWidth));
83
+ propsStyleChanged = true;
84
+ }
85
+
86
+ if (!isnan(state._styleHeight)) {
87
+ style.setDimension(facebook::yoga::Dimension::Height,
88
+ facebook::yoga::StyleSizeLength::points(state._styleHeight));
89
+ propsStyleChanged = true;
90
+ }
91
+
92
+ if (propsStyleChanged) {
93
+ // Updates yoga style from props and sets the node dirty
94
+ snode->updateYogaProps();
95
+ }
96
+
97
+ // Writes the node style directly, so it runs last.
65
98
  auto width = state._width;
66
99
  auto height = state._height;
67
100
 
68
101
  if (!isnan(width) || !isnan(height)) {
69
- auto const &props = *std::static_pointer_cast<const facebook::react::ViewProps>(
70
- snode->getProps());
71
-
72
102
  // The node has width and/or height set as style props, so we should not override it
73
- auto widthProp = props.yogaStyle.dimension(facebook::yoga::Dimension::Width);
74
- auto heightProp = props.yogaStyle.dimension(facebook::yoga::Dimension::Height);
103
+ auto widthProp = style.dimension(facebook::yoga::Dimension::Width);
104
+ auto heightProp = style.dimension(facebook::yoga::Dimension::Height);
75
105
 
76
106
  if (widthProp.value().isDefined()) {
77
107
  // view has fixed dimension size set in props, so we should not autosize it in that axis
@@ -84,44 +114,6 @@ public:
84
114
  snode->setSize({width, height});
85
115
  }
86
116
 
87
- // handle layout style prop update
88
- auto styleWidth = state._styleWidth;
89
- auto styleHeight = state._styleHeight;
90
-
91
- if (!isnan(styleWidth) || !isnan(styleHeight)) {
92
- auto const &props = *std::static_pointer_cast<const facebook::react::ViewProps>(
93
- snode->getProps());
94
-
95
- auto &style = const_cast<facebook::yoga::Style &>(props.yogaStyle);
96
-
97
- if (!isnan(styleWidth)) {
98
- style.setDimension(facebook::yoga::Dimension::Width,
99
- facebook::yoga::StyleSizeLength::points(styleWidth));
100
- }
101
-
102
- if (!isnan(styleHeight)) {
103
- style.setDimension(facebook::yoga::Dimension::Height,
104
- facebook::yoga::StyleSizeLength::points(styleHeight));
105
- }
106
-
107
- // Updates yoga style from props and sets the node dirty
108
- snode->updateYogaProps();
109
- }
110
-
111
- if (isRNHostView(snode->getProps())) {
112
- auto const &props = *std::static_pointer_cast<const facebook::react::ViewProps>(
113
- snode->getProps());
114
- auto &style = const_cast<facebook::yoga::Style &>(props.yogaStyle);
115
-
116
- // If RNHostView has align self set to auto or stretch, we should override it to flex-start so that the node can size itself to its content
117
- auto const alignSelf = style.alignSelf();
118
-
119
- if (alignSelf == facebook::yoga::Align::Auto || alignSelf == facebook::yoga::Align::Stretch) {
120
- style.setAlignSelf(facebook::yoga::Align::FlexStart);
121
- snode->updateYogaProps();
122
- }
123
- }
124
-
125
117
  facebook::react::ConcreteComponentDescriptor<ShadowNodeType>::adopt(shadowNode);
126
118
  }
127
119
  };
@@ -163,6 +163,20 @@ private:
163
163
  }
164
164
 
165
165
  react::LayoutConstraints hostedContentConstraints(const react::ShadowNode &content) const {
166
+ auto constraints = contentStyleConstraints(content);
167
+
168
+ // An unmatched axis has the size SwiftUI or Compose gave the host (from `setViewSize`), so lay
169
+ // the content out at exactly that size. This overrides the content's own min/max on that axis.
170
+ auto const &ownStyle = this->yogaNode_.style();
171
+ constrainExactlyToPoints(ownStyle.dimension(facebook::yoga::Dimension::Width),
172
+ constraints.minimumSize.width, constraints.maximumSize.width);
173
+ constrainExactlyToPoints(ownStyle.dimension(facebook::yoga::Dimension::Height),
174
+ constraints.minimumSize.height, constraints.maximumSize.height);
175
+
176
+ return constraints;
177
+ }
178
+
179
+ react::LayoutConstraints contentStyleConstraints(const react::ShadowNode &content) const {
166
180
  react::LayoutConstraints constraints{};
167
181
  constraints.layoutDirection = resolvedLayoutDirection();
168
182
 
@@ -186,6 +200,14 @@ private:
186
200
  return constraints;
187
201
  }
188
202
 
203
+ static void constrainExactlyToPoints(facebook::yoga::StyleSizeLength length,
204
+ react::Float &minimum,
205
+ react::Float &maximum) {
206
+ if (length.isPoints() && length.value().isDefined()) {
207
+ minimum = maximum = std::max<react::Float>(0, length.value().unwrap());
208
+ }
209
+ }
210
+
189
211
  static void constrainToPoints(facebook::yoga::StyleSizeLength length, react::Float &constraint) {
190
212
  if (length.isPoints() && length.value().isDefined()) {
191
213
  constraint = std::max<react::Float>(0, length.value().unwrap());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-modules-core",
3
- "version": "58.0.9",
3
+ "version": "58.0.10",
4
4
  "description": "The core of Expo Modules architecture",
5
5
  "keywords": [
6
6
  "expo",
@@ -64,7 +64,7 @@
64
64
  "./package.json": "./package.json"
65
65
  },
66
66
  "dependencies": {
67
- "expo-modules-jsi": "~58.0.5",
67
+ "expo-modules-jsi": "~58.0.6",
68
68
  "expo-modules-macros": "0.14.0",
69
69
  "invariant": "^2.2.4"
70
70
  },