expo-modules-core 2.3.9 → 2.3.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
@@ -10,6 +10,12 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 2.3.10 — 2025-04-28
14
+
15
+ ### 🐛 Bug fixes
16
+
17
+ - [iOS] Fix concurrent functions on views. ([#36431](https://github.com/expo/expo/pull/36431) by [@alanjhughes](https://github.com/alanjhughes))
18
+
13
19
  ## 2.3.9 — 2025-04-25
14
20
 
15
21
  ### 💡 Others
@@ -25,7 +25,7 @@ if (shouldIncludeCompose) {
25
25
  }
26
26
 
27
27
  group = 'host.exp.exponent'
28
- version = '2.3.9'
28
+ version = '2.3.10'
29
29
 
30
30
  def isExpoModulesCoreTests = {
31
31
  Gradle gradle = getGradle()
@@ -75,7 +75,7 @@ android {
75
75
  defaultConfig {
76
76
  consumerProguardFiles 'proguard-rules.pro'
77
77
  versionCode 1
78
- versionName "2.3.9"
78
+ versionName "2.3.10"
79
79
  buildConfigField "String", "EXPO_MODULES_CORE_VERSION", "\"${versionName}\""
80
80
  buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled.toString()
81
81
 
@@ -55,6 +55,11 @@ public struct ViewDefinitionBuilder<ViewType: UIView> {
55
55
  function.runOnQueue(.main)
56
56
  function.takesOwner = true
57
57
  }
58
+
59
+ if var function = element as? AnyConcurrentFunctionDefinition {
60
+ function.requiresMainActor = true
61
+ function.takesOwner = true
62
+ }
58
63
  return element
59
64
  }
60
65
  }
@@ -9,6 +9,7 @@ internal protocol AnyAsyncFunctionDefinition: AnyFunctionDefinition {
9
9
  /**
10
10
  Specifies on which queue the function should run.
11
11
  */
12
+ @discardableResult
12
13
  func runOnQueue(_ queue: DispatchQueue?) -> Self
13
14
  }
14
15
 
@@ -1,10 +1,20 @@
1
1
  // Copyright 2022-present 650 Industries. All rights reserved.
2
2
 
3
+ /**
4
+ Type-erased protocol for asynchronous functions using Swift concurrency
5
+ */
6
+ internal protocol AnyConcurrentFunctionDefinition: AnyFunctionDefinition {
7
+ /**
8
+ Specifies if the main actor should be used. Necessary when attached to a view
9
+ */
10
+ var requiresMainActor: Bool { get set }
11
+ }
12
+
3
13
  /**
4
14
  Represents a concurrent function that can only be called asynchronously, thus its JavaScript equivalent returns a Promise.
5
15
  As opposed to `AsyncFunctionDefinition`, it can leverage the new Swift's concurrency model and take the async/await closure.
6
16
  */
7
- public final class ConcurrentFunctionDefinition<Args, FirstArgType, ReturnType>: AnyFunctionDefinition {
17
+ public final class ConcurrentFunctionDefinition<Args, FirstArgType, ReturnType>: AnyConcurrentFunctionDefinition {
8
18
  typealias ClosureType = (Args) async throws -> ReturnType
9
19
 
10
20
  let body: ClosureType
@@ -31,6 +41,7 @@ public final class ConcurrentFunctionDefinition<Args, FirstArgType, ReturnType>:
31
41
  }
32
42
 
33
43
  var takesOwner: Bool = false
44
+ var requiresMainActor: Bool = false
34
45
 
35
46
  func call(by owner: AnyObject?, withArguments args: [Any], appContext: AppContext, callback: @escaping (FunctionCallResult) -> Void) {
36
47
  var arguments: [Any]
@@ -62,7 +73,14 @@ public final class ConcurrentFunctionDefinition<Args, FirstArgType, ReturnType>:
62
73
 
63
74
  do {
64
75
  // Convert arguments to the types desired by the function.
65
- let finalArguments = try cast(arguments: arguments, forFunction: self, appContext: appContext)
76
+ var finalArguments: [Any]
77
+ if requiresMainActor {
78
+ finalArguments = try await MainActor.run {
79
+ try cast(arguments: arguments, forFunction: self, appContext: appContext)
80
+ }
81
+ } else {
82
+ finalArguments = try cast(arguments: arguments, forFunction: self, appContext: appContext)
83
+ }
66
84
 
67
85
  // TODO: Right now we force cast the tuple in all types of functions, but we should throw another exception here.
68
86
  // swiftlint:disable force_cast
@@ -30,6 +30,11 @@ extension ExpoSwiftUI {
30
30
  function.runOnQueue(.main)
31
31
  function.takesOwner = true
32
32
  }
33
+
34
+ if var function = element as? AnyConcurrentFunctionDefinition {
35
+ function.requiresMainActor = true
36
+ function.takesOwner = true
37
+ }
33
38
  return element
34
39
  }
35
40
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-modules-core",
3
- "version": "2.3.9",
3
+ "version": "2.3.10",
4
4
  "description": "The core of Expo Modules architecture",
5
5
  "main": "src/index.ts",
6
6
  "types": "build/index.d.ts",
@@ -44,5 +44,5 @@
44
44
  "@testing-library/react-native": "^13.1.0",
45
45
  "expo-module-scripts": "^4.1.5"
46
46
  },
47
- "gitHead": "3cd208465df78e385ca9380531bbbfe33ca68e81"
47
+ "gitHead": "a639a661a5329e58f916cf69b8f1a7718bbdd26e"
48
48
  }