expo-modules-core 2.3.8 → 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.
Files changed (33) hide show
  1. package/CHANGELOG.md +14 -1
  2. package/android/build.gradle +22 -9
  3. package/android/src/compose/expo/modules/kotlin/views/ModuleDefinitionBuilderComposeExtension.kt +35 -0
  4. package/android/src/main/java/expo/modules/kotlin/ModuleHolder.kt +2 -2
  5. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionBuilder.kt +17 -17
  6. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionComponent.kt +75 -68
  7. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionWithPromiseComponent.kt +1 -1
  8. package/android/src/main/java/expo/modules/kotlin/functions/UntypedAsyncFunctionComponent.kt +84 -0
  9. package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionBuilder.kt +8 -25
  10. package/android/src/main/java/expo/modules/kotlin/objects/ObjectDefinitionBuilder.kt +19 -19
  11. package/android/src/main/java/expo/modules/kotlin/views/ViewDefinitionBuilder.kt +19 -19
  12. package/android/src/withoutCompose/expo/modules/kotlin/views/ModuleDefinitionBuilderComposeExtension.kt +10 -0
  13. package/common/cpp/TestingSyncJSCallInvoker.h +0 -10
  14. package/ios/Api/Builders/ViewDefinitionBuilder.swift +5 -0
  15. package/ios/Core/Functions/AsyncFunctionDefinition.swift +1 -0
  16. package/ios/Core/Functions/ConcurrentFunctionDefinition.swift +20 -2
  17. package/ios/Core/Promise.swift +8 -6
  18. package/ios/Core/Views/SwiftUI/SwiftUIViewDefinition.swift +2 -1
  19. package/ios/Core/Views/SwiftUI/SwiftUIViewDefinitionBuilder.swift +5 -0
  20. package/ios/JSI/EXJSIConversions.mm +4 -0
  21. package/ios/JSI/EXJavaScriptRuntime.mm +2 -2
  22. package/ios/JSI/EXJavaScriptSharedObjectBinding.h +25 -0
  23. package/ios/JSI/EXJavaScriptSharedObjectBinding.mm +24 -0
  24. package/ios/TestUtils/MainThreadInvoker.h +14 -0
  25. package/ios/TestUtils/MainThreadInvoker.mm +19 -0
  26. package/ios/TestUtils/TestingJSCallInvoker.h +46 -0
  27. package/ios/Tests/FunctionSpec.swift +18 -6
  28. package/package.json +3 -3
  29. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunction.kt +0 -91
  30. /package/android/src/{main/java → compose}/expo/modules/kotlin/views/AutoSizingComposable.kt +0 -0
  31. /package/android/src/{main/java → compose}/expo/modules/kotlin/views/ComposeProps.kt +0 -0
  32. /package/android/src/{main/java → compose}/expo/modules/kotlin/views/ComposeViewProp.kt +0 -0
  33. /package/android/src/{main/java → compose}/expo/modules/kotlin/views/ExpoComposeView.kt +0 -0
@@ -8,7 +8,7 @@ import expo.modules.kotlin.component6
8
8
  import expo.modules.kotlin.component7
9
9
  import expo.modules.kotlin.component8
10
10
  import expo.modules.kotlin.events.EventsDefinition
11
- import expo.modules.kotlin.functions.AsyncFunction
11
+ import expo.modules.kotlin.functions.AsyncFunctionComponent
12
12
  import expo.modules.kotlin.functions.AsyncFunctionBuilder
13
13
  import expo.modules.kotlin.functions.AsyncFunctionWithPromiseComponent
14
14
  import expo.modules.kotlin.functions.FunctionBuilder
@@ -47,7 +47,7 @@ open class ObjectDefinitionBuilder(customConverter: TypeConverterProvider? = nul
47
47
  internal var syncFunctionBuilder = mutableMapOf<String, FunctionBuilder>()
48
48
 
49
49
  @PublishedApi
50
- internal var asyncFunctions = mutableMapOf<String, AsyncFunction>()
50
+ internal var asyncFunctions = mutableMapOf<String, AsyncFunctionComponent>()
51
51
 
52
52
  private var asyncFunctionBuilders = mutableMapOf<String, AsyncFunctionBuilder>()
53
53
 
@@ -222,7 +222,7 @@ open class ObjectDefinitionBuilder(customConverter: TypeConverterProvider? = nul
222
222
  inline fun AsyncFunction(
223
223
  name: String,
224
224
  crossinline body: () -> Any?
225
- ): AsyncFunction {
225
+ ): AsyncFunctionComponent {
226
226
  return createAsyncFunctionComponent(name, emptyArray()) { body() }.also {
227
227
  asyncFunctions[name] = it
228
228
  }
@@ -231,7 +231,7 @@ open class ObjectDefinitionBuilder(customConverter: TypeConverterProvider? = nul
231
231
  inline fun <reified R> AsyncFunction(
232
232
  name: String,
233
233
  crossinline body: () -> R
234
- ): AsyncFunction {
234
+ ): AsyncFunctionComponent {
235
235
  return createAsyncFunctionComponent(name, emptyArray()) { body() }.also {
236
236
  asyncFunctions[name] = it
237
237
  }
@@ -240,7 +240,7 @@ open class ObjectDefinitionBuilder(customConverter: TypeConverterProvider? = nul
240
240
  inline fun <reified R, reified P0> AsyncFunction(
241
241
  name: String,
242
242
  crossinline body: (p0: P0) -> R
243
- ): AsyncFunction {
243
+ ): AsyncFunctionComponent {
244
244
  // We can't split that function, because that introduces a ambiguity when creating DSL component without parameters.
245
245
  return if (P0::class.java == Promise::class.java) {
246
246
  AsyncFunctionWithPromiseComponent(name, arrayOf()) { _, promise -> body(promise as P0) }
@@ -257,7 +257,7 @@ open class ObjectDefinitionBuilder(customConverter: TypeConverterProvider? = nul
257
257
  inline fun <reified R, reified P0, reified P1> AsyncFunction(
258
258
  name: String,
259
259
  crossinline body: (p0: P0, p1: P1) -> R
260
- ): AsyncFunction {
260
+ ): AsyncFunctionComponent {
261
261
  return createAsyncFunctionComponent(name, toArgsArray<P0, P1>()) { (p0, p1) ->
262
262
  enforceType<P0, P1>(p0, p1)
263
263
  body(p0, p1)
@@ -270,7 +270,7 @@ open class ObjectDefinitionBuilder(customConverter: TypeConverterProvider? = nul
270
270
  inline fun <reified R, reified P0> AsyncFunction(
271
271
  name: String,
272
272
  crossinline body: (p0: P0, p1: Promise) -> R
273
- ): AsyncFunction {
273
+ ): AsyncFunctionComponent {
274
274
  return AsyncFunctionWithPromiseComponent(name, toArgsArray<P0>()) { (p0), promise ->
275
275
  enforceType<P0>(p0)
276
276
  body(p0, promise)
@@ -282,7 +282,7 @@ open class ObjectDefinitionBuilder(customConverter: TypeConverterProvider? = nul
282
282
  inline fun <reified R, reified P0, reified P1, reified P2> AsyncFunction(
283
283
  name: String,
284
284
  crossinline body: (p0: P0, p1: P1, p2: P2) -> R
285
- ): AsyncFunction {
285
+ ): AsyncFunctionComponent {
286
286
  return createAsyncFunctionComponent(name, toArgsArray<P0, P1, P2>()) { (p0, p1, p2) ->
287
287
  enforceType<P0, P1, P2>(p0, p1, p2)
288
288
  body(p0, p1, p2)
@@ -295,7 +295,7 @@ open class ObjectDefinitionBuilder(customConverter: TypeConverterProvider? = nul
295
295
  inline fun <reified R, reified P0, reified P1> AsyncFunction(
296
296
  name: String,
297
297
  crossinline body: (p0: P0, p1: P1, p2: Promise) -> R
298
- ): AsyncFunction {
298
+ ): AsyncFunctionComponent {
299
299
  return AsyncFunctionWithPromiseComponent(name, toArgsArray<P0, P1>()) { (p0, p1), promise ->
300
300
  enforceType<P0, P1>(p0, p1)
301
301
  body(p0, p1, promise)
@@ -307,7 +307,7 @@ open class ObjectDefinitionBuilder(customConverter: TypeConverterProvider? = nul
307
307
  inline fun <reified R, reified P0, reified P1, reified P2, reified P3> AsyncFunction(
308
308
  name: String,
309
309
  crossinline body: (p0: P0, p1: P1, p2: P2, p3: P3) -> R
310
- ): AsyncFunction {
310
+ ): AsyncFunctionComponent {
311
311
  return createAsyncFunctionComponent(name, toArgsArray<P0, P1, P2, P3>()) { (p0, p1, p2, p3) ->
312
312
  enforceType<P0, P1, P2, P3>(p0, p1, p2, p3)
313
313
  body(p0, p1, p2, p3)
@@ -320,7 +320,7 @@ open class ObjectDefinitionBuilder(customConverter: TypeConverterProvider? = nul
320
320
  inline fun <reified R, reified P0, reified P1, reified P2> AsyncFunction(
321
321
  name: String,
322
322
  crossinline body: (p0: P0, p1: P1, p2: P2, p3: Promise) -> R
323
- ): AsyncFunction {
323
+ ): AsyncFunctionComponent {
324
324
  return AsyncFunctionWithPromiseComponent(name, toArgsArray<P0, P1, P2>()) { (p0, p1, p2), promise ->
325
325
  enforceType<P0, P1, P2>(p0, p1, p2)
326
326
  body(p0, p1, p2, promise)
@@ -332,7 +332,7 @@ open class ObjectDefinitionBuilder(customConverter: TypeConverterProvider? = nul
332
332
  inline fun <reified R, reified P0, reified P1, reified P2, reified P3, reified P4> AsyncFunction(
333
333
  name: String,
334
334
  crossinline body: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4) -> R
335
- ): AsyncFunction {
335
+ ): AsyncFunctionComponent {
336
336
  return createAsyncFunctionComponent(name, toArgsArray<P0, P1, P2, P3, P4>()) { (p0, p1, p2, p3, p4) ->
337
337
  enforceType<P0, P1, P2, P3, P4>(p0, p1, p2, p3, p4)
338
338
  body(p0, p1, p2, p3, p4)
@@ -345,7 +345,7 @@ open class ObjectDefinitionBuilder(customConverter: TypeConverterProvider? = nul
345
345
  inline fun <reified R, reified P0, reified P1, reified P2, reified P3> AsyncFunction(
346
346
  name: String,
347
347
  crossinline body: (p0: P0, p1: P1, p2: P2, p3: P3, p4: Promise) -> R
348
- ): AsyncFunction {
348
+ ): AsyncFunctionComponent {
349
349
  return AsyncFunctionWithPromiseComponent(name, toArgsArray<P0, P1, P2, P3>()) { (p0, p1, p2, p3), promise ->
350
350
  enforceType<P0, P1, P2, P3>(p0, p1, p2, p3)
351
351
  body(p0, p1, p2, p3, promise)
@@ -357,7 +357,7 @@ open class ObjectDefinitionBuilder(customConverter: TypeConverterProvider? = nul
357
357
  inline fun <reified R, reified P0, reified P1, reified P2, reified P3, reified P4, reified P5> AsyncFunction(
358
358
  name: String,
359
359
  crossinline body: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5) -> R
360
- ): AsyncFunction {
360
+ ): AsyncFunctionComponent {
361
361
  return createAsyncFunctionComponent(name, toArgsArray<P0, P1, P2, P3, P4, P5>()) { (p0, p1, p2, p3, p4, p5) ->
362
362
  enforceType<P0, P1, P2, P3, P4, P5>(p0, p1, p2, p3, p4, p5)
363
363
  body(p0, p1, p2, p3, p4, p5)
@@ -370,7 +370,7 @@ open class ObjectDefinitionBuilder(customConverter: TypeConverterProvider? = nul
370
370
  inline fun <reified R, reified P0, reified P1, reified P2, reified P3, reified P4> AsyncFunction(
371
371
  name: String,
372
372
  crossinline body: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: Promise) -> R
373
- ): AsyncFunction {
373
+ ): AsyncFunctionComponent {
374
374
  return AsyncFunctionWithPromiseComponent(name, toArgsArray<P0, P1, P2, P3, P4>()) { (p0, p1, p2, p3, p4), promise ->
375
375
  enforceType<P0, P1, P2, P3, P4>(p0, p1, p2, p3, p4)
376
376
  body(p0, p1, p2, p3, p4, promise)
@@ -382,7 +382,7 @@ open class ObjectDefinitionBuilder(customConverter: TypeConverterProvider? = nul
382
382
  inline fun <reified R, reified P0, reified P1, reified P2, reified P3, reified P4, reified P5, reified P6> AsyncFunction(
383
383
  name: String,
384
384
  crossinline body: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6) -> R
385
- ): AsyncFunction {
385
+ ): AsyncFunctionComponent {
386
386
  return createAsyncFunctionComponent(name, toArgsArray<P0, P1, P2, P3, P4, P5, P6>()) { (p0, p1, p2, p3, p4, p5, p6) ->
387
387
  enforceType<P0, P1, P2, P3, P4, P5, P6>(p0, p1, p2, p3, p4, p5, p6)
388
388
  body(p0, p1, p2, p3, p4, p5, p6)
@@ -395,7 +395,7 @@ open class ObjectDefinitionBuilder(customConverter: TypeConverterProvider? = nul
395
395
  inline fun <reified R, reified P0, reified P1, reified P2, reified P3, reified P4, reified P5> AsyncFunction(
396
396
  name: String,
397
397
  crossinline body: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: Promise) -> R
398
- ): AsyncFunction {
398
+ ): AsyncFunctionComponent {
399
399
  return AsyncFunctionWithPromiseComponent(name, toArgsArray<P0, P1, P2, P3, P4, P5>()) { (p0, p1, p2, p3, p4, p5), promise ->
400
400
  enforceType<P0, P1, P2, P3, P4, P5>(p0, p1, p2, p3, p4, p5)
401
401
  body(p0, p1, p2, p3, p4, p5, promise)
@@ -407,7 +407,7 @@ open class ObjectDefinitionBuilder(customConverter: TypeConverterProvider? = nul
407
407
  inline fun <reified R, reified P0, reified P1, reified P2, reified P3, reified P4, reified P5, reified P6, reified P7> AsyncFunction(
408
408
  name: String,
409
409
  crossinline body: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7) -> R
410
- ): AsyncFunction {
410
+ ): AsyncFunctionComponent {
411
411
  return createAsyncFunctionComponent(name, toArgsArray<P0, P1, P2, P3, P4, P5, P6, P7>()) { (p0, p1, p2, p3, p4, p5, p6, p7) ->
412
412
  enforceType<P0, P1, P2, P3, P4, P5, P6, P7>(p0, p1, p2, p3, p4, p5, p6, p7)
413
413
  body(p0, p1, p2, p3, p4, p5, p6, p7)
@@ -420,7 +420,7 @@ open class ObjectDefinitionBuilder(customConverter: TypeConverterProvider? = nul
420
420
  inline fun <reified R, reified P0, reified P1, reified P2, reified P3, reified P4, reified P5, reified P6> AsyncFunction(
421
421
  name: String,
422
422
  crossinline body: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: Promise) -> R
423
- ): AsyncFunction {
423
+ ): AsyncFunctionComponent {
424
424
  return AsyncFunctionWithPromiseComponent(name, toArgsArray<P0, P1, P2, P3, P4, P5, P6>()) { (p0, p1, p2, p3, p4, p5, p6), promise ->
425
425
  enforceType<P0, P1, P2, P3, P4, P5, P6>(p0, p1, p2, p3, p4, p5, p6)
426
426
  body(p0, p1, p2, p3, p4, p5, p6, promise)
@@ -13,7 +13,7 @@ import expo.modules.kotlin.component7
13
13
  import expo.modules.kotlin.component8
14
14
  import expo.modules.kotlin.exception.CodedException
15
15
  import expo.modules.kotlin.exception.UnexpectedException
16
- import expo.modules.kotlin.functions.AsyncFunction
16
+ import expo.modules.kotlin.functions.AsyncFunctionComponent
17
17
  import expo.modules.kotlin.functions.AsyncFunctionBuilder
18
18
  import expo.modules.kotlin.functions.AsyncFunctionWithPromiseComponent
19
19
  import expo.modules.kotlin.functions.Queues
@@ -47,7 +47,7 @@ class ViewDefinitionBuilder<T : View>(
47
47
  private var callbacksDefinition: CallbacksDefinition? = null
48
48
 
49
49
  @PublishedApi
50
- internal var asyncFunctions = mutableMapOf<String, AsyncFunction>()
50
+ internal var asyncFunctions = mutableMapOf<String, AsyncFunctionComponent>()
51
51
 
52
52
  private var functionBuilders = mutableMapOf<String, AsyncFunctionBuilder>()
53
53
 
@@ -193,7 +193,7 @@ class ViewDefinitionBuilder<T : View>(
193
193
  inline fun AsyncFunction(
194
194
  name: String,
195
195
  crossinline body: () -> Any?
196
- ): AsyncFunction {
196
+ ): AsyncFunctionComponent {
197
197
  return createAsyncFunctionComponent(name, emptyArray()) { body() }.also {
198
198
  asyncFunctions[name] = it
199
199
  }
@@ -202,7 +202,7 @@ class ViewDefinitionBuilder<T : View>(
202
202
  inline fun <reified R> AsyncFunction(
203
203
  name: String,
204
204
  crossinline body: () -> R
205
- ): AsyncFunction {
205
+ ): AsyncFunctionComponent {
206
206
  return createAsyncFunctionComponent(name, emptyArray()) { body() }.also {
207
207
  asyncFunctions[name] = it
208
208
  }
@@ -211,7 +211,7 @@ class ViewDefinitionBuilder<T : View>(
211
211
  inline fun <reified R, reified P0> AsyncFunction(
212
212
  name: String,
213
213
  crossinline body: (p0: P0) -> R
214
- ): AsyncFunction {
214
+ ): AsyncFunctionComponent {
215
215
  // We can't split that function, because that introduces a ambiguity when creating DSL component without parameters.
216
216
  return if (P0::class == Promise::class) {
217
217
  AsyncFunctionWithPromiseComponent(name, emptyArray()) { _, promise -> body(promise as P0) }
@@ -228,7 +228,7 @@ class ViewDefinitionBuilder<T : View>(
228
228
  inline fun <reified R, reified P0, reified P1> AsyncFunction(
229
229
  name: String,
230
230
  crossinline body: (p0: P0, p1: P1) -> R
231
- ): AsyncFunction {
231
+ ): AsyncFunctionComponent {
232
232
  return createAsyncFunctionComponent(name, toArgsArray<P0, P1>()) { (p0, p1) ->
233
233
  enforceType<P0, P1>(p0, p1)
234
234
  body(p0, p1)
@@ -241,7 +241,7 @@ class ViewDefinitionBuilder<T : View>(
241
241
  inline fun <reified R, reified P0> AsyncFunction(
242
242
  name: String,
243
243
  crossinline body: (p0: P0, p1: Promise) -> R
244
- ): AsyncFunction {
244
+ ): AsyncFunctionComponent {
245
245
  return AsyncFunctionWithPromiseComponent(name, toArgsArray<P0>()) { (p0), promise ->
246
246
  enforceType<P0>(p0)
247
247
  body(p0, promise)
@@ -253,7 +253,7 @@ class ViewDefinitionBuilder<T : View>(
253
253
  inline fun <reified R, reified P0, reified P1, reified P2> AsyncFunction(
254
254
  name: String,
255
255
  crossinline body: (p0: P0, p1: P1, p2: P2) -> R
256
- ): AsyncFunction {
256
+ ): AsyncFunctionComponent {
257
257
  return createAsyncFunctionComponent(name, toArgsArray<P0, P1, P2>()) { (p0, p1, p2) ->
258
258
  enforceType<P0, P1, P2>(p0, p1, p2)
259
259
  body(p0, p1, p2)
@@ -266,7 +266,7 @@ class ViewDefinitionBuilder<T : View>(
266
266
  inline fun <reified R, reified P0, reified P1> AsyncFunction(
267
267
  name: String,
268
268
  crossinline body: (p0: P0, p1: P1, p2: Promise) -> R
269
- ): AsyncFunction {
269
+ ): AsyncFunctionComponent {
270
270
  return AsyncFunctionWithPromiseComponent(name, toArgsArray<P0, P1>()) { (p0, p1), promise ->
271
271
  enforceType<P0, P1>(p0, p1)
272
272
  body(p0, p1, promise)
@@ -278,7 +278,7 @@ class ViewDefinitionBuilder<T : View>(
278
278
  inline fun <reified R, reified P0, reified P1, reified P2, reified P3> AsyncFunction(
279
279
  name: String,
280
280
  crossinline body: (p0: P0, p1: P1, p2: P2, p3: P3) -> R
281
- ): AsyncFunction {
281
+ ): AsyncFunctionComponent {
282
282
  return createAsyncFunctionComponent(name, toArgsArray<P0, P1, P2, P3>()) { (p0, p1, p2, p3) ->
283
283
  enforceType<P0, P1, P2, P3>(p0, p1, p2, p3)
284
284
  body(p0, p1, p2, p3)
@@ -291,7 +291,7 @@ class ViewDefinitionBuilder<T : View>(
291
291
  inline fun <reified R, reified P0, reified P1, reified P2> AsyncFunction(
292
292
  name: String,
293
293
  crossinline body: (p0: P0, p1: P1, p2: P2, p3: Promise) -> R
294
- ): AsyncFunction {
294
+ ): AsyncFunctionComponent {
295
295
  return AsyncFunctionWithPromiseComponent(name, toArgsArray<P0, P1, P2>()) { (p0, p1, p2), promise ->
296
296
  enforceType<P0, P1, P2>(p0, p1, p2)
297
297
  body(p0, p1, p2, promise)
@@ -303,7 +303,7 @@ class ViewDefinitionBuilder<T : View>(
303
303
  inline fun <reified R, reified P0, reified P1, reified P2, reified P3, reified P4> AsyncFunction(
304
304
  name: String,
305
305
  crossinline body: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4) -> R
306
- ): AsyncFunction {
306
+ ): AsyncFunctionComponent {
307
307
  return createAsyncFunctionComponent(name, toArgsArray<P0, P1, P2, P3, P4>()) { (p0, p1, p2, p3, p4) ->
308
308
  enforceType<P0, P1, P2, P3, P4>(p0, p1, p2, p3, p4)
309
309
  body(p0, p1, p2, p3, p4)
@@ -316,7 +316,7 @@ class ViewDefinitionBuilder<T : View>(
316
316
  inline fun <reified R, reified P0, reified P1, reified P2, reified P3> AsyncFunction(
317
317
  name: String,
318
318
  crossinline body: (p0: P0, p1: P1, p2: P2, p3: P3, p4: Promise) -> R
319
- ): AsyncFunction {
319
+ ): AsyncFunctionComponent {
320
320
  return AsyncFunctionWithPromiseComponent(name, toArgsArray<P0, P1, P2, P3>()) { (p0, p1, p2, p3), promise ->
321
321
  enforceType<P0, P1, P2, P3>(p0, p1, p2, p3)
322
322
  body(p0, p1, p2, p3, promise)
@@ -328,7 +328,7 @@ class ViewDefinitionBuilder<T : View>(
328
328
  inline fun <reified R, reified P0, reified P1, reified P2, reified P3, reified P4, reified P5> AsyncFunction(
329
329
  name: String,
330
330
  crossinline body: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5) -> R
331
- ): AsyncFunction {
331
+ ): AsyncFunctionComponent {
332
332
  return createAsyncFunctionComponent(name, toArgsArray<P0, P1, P2, P3, P4, P5>()) { (p0, p1, p2, p3, p4, p5) ->
333
333
  enforceType<P0, P1, P2, P3, P4, P5>(p0, p1, p2, p3, p4, p5)
334
334
  body(p0, p1, p2, p3, p4, p5)
@@ -341,7 +341,7 @@ class ViewDefinitionBuilder<T : View>(
341
341
  inline fun <reified R, reified P0, reified P1, reified P2, reified P3, reified P4> AsyncFunction(
342
342
  name: String,
343
343
  crossinline body: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: Promise) -> R
344
- ): AsyncFunction {
344
+ ): AsyncFunctionComponent {
345
345
  return AsyncFunctionWithPromiseComponent(name, toArgsArray<P0, P1, P2, P3, P4>()) { (p0, p1, p2, p3, p4), promise ->
346
346
  enforceType<P0, P1, P2, P3, P4>(p0, p1, p2, p3, p4)
347
347
  body(p0, p1, p2, p3, p4, promise)
@@ -353,7 +353,7 @@ class ViewDefinitionBuilder<T : View>(
353
353
  inline fun <reified R, reified P0, reified P1, reified P2, reified P3, reified P4, reified P5, reified P6> AsyncFunction(
354
354
  name: String,
355
355
  crossinline body: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6) -> R
356
- ): AsyncFunction {
356
+ ): AsyncFunctionComponent {
357
357
  return createAsyncFunctionComponent(name, toArgsArray<P0, P1, P2, P3, P4, P5, P6>()) { (p0, p1, p2, p3, p4, p5, p6) ->
358
358
  enforceType<P0, P1, P2, P3, P4, P5, P6>(p0, p1, p2, p3, p4, p5, p6)
359
359
  body(p0, p1, p2, p3, p4, p5, p6)
@@ -366,7 +366,7 @@ class ViewDefinitionBuilder<T : View>(
366
366
  inline fun <reified R, reified P0, reified P1, reified P2, reified P3, reified P4, reified P5> AsyncFunction(
367
367
  name: String,
368
368
  crossinline body: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: Promise) -> R
369
- ): AsyncFunction {
369
+ ): AsyncFunctionComponent {
370
370
  return AsyncFunctionWithPromiseComponent(name, toArgsArray<P0, P1, P2, P3, P4, P5>()) { (p0, p1, p2, p3, p4, p5), promise ->
371
371
  enforceType<P0, P1, P2, P3, P4, P5>(p0, p1, p2, p3, p4, p5)
372
372
  body(p0, p1, p2, p3, p4, p5, promise)
@@ -378,7 +378,7 @@ class ViewDefinitionBuilder<T : View>(
378
378
  inline fun <reified R, reified P0, reified P1, reified P2, reified P3, reified P4, reified P5, reified P6, reified P7> AsyncFunction(
379
379
  name: String,
380
380
  crossinline body: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7) -> R
381
- ): AsyncFunction {
381
+ ): AsyncFunctionComponent {
382
382
  return createAsyncFunctionComponent(name, toArgsArray<P0, P1, P2, P3, P4, P5, P6, P7>()) { (p0, p1, p2, p3, p4, p5, p6, p7) ->
383
383
  enforceType<P0, P1, P2, P3, P4, P5, P6, P7>(p0, p1, p2, p3, p4, p5, p6, p7)
384
384
  body(p0, p1, p2, p3, p4, p5, p6, p7)
@@ -391,7 +391,7 @@ class ViewDefinitionBuilder<T : View>(
391
391
  inline fun <reified R, reified P0, reified P1, reified P2, reified P3, reified P4, reified P5, reified P6> AsyncFunction(
392
392
  name: String,
393
393
  crossinline body: (p0: P0, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: Promise) -> R
394
- ): AsyncFunction {
394
+ ): AsyncFunctionComponent {
395
395
  return AsyncFunctionWithPromiseComponent(name, toArgsArray<P0, P1, P2, P3, P4, P5, P6>()) { (p0, p1, p2, p3, p4, p5, p6), promise ->
396
396
  enforceType<P0, P1, P2, P3, P4, P5, P6>(p0, p1, p2, p3, p4, p5, p6)
397
397
  body(p0, p1, p2, p3, p4, p5, p6, promise)
@@ -0,0 +1,10 @@
1
+ @file:Suppress("FunctionName")
2
+
3
+ package expo.modules.kotlin.views
4
+
5
+ import expo.modules.kotlin.modules.InternalModuleDefinitionBuilder
6
+ import expo.modules.kotlin.modules.Module
7
+
8
+ open class ModuleDefinitionBuilderWithCompose(
9
+ module: Module? = null
10
+ ) : InternalModuleDefinitionBuilder(module)
@@ -21,7 +21,6 @@ class TestingSyncJSCallInvoker : public react::CallInvoker {
21
21
  public:
22
22
  explicit TestingSyncJSCallInvoker(const std::shared_ptr<jsi::Runtime>& runtime) : runtime(runtime) {}
23
23
 
24
- #if REACT_NATIVE_TARGET_VERSION >= 75
25
24
  void invokeAsync(react::CallFunc &&func) noexcept override {
26
25
  func(*runtime.lock());
27
26
  }
@@ -29,15 +28,6 @@ public:
29
28
  void invokeSync(react::CallFunc &&func) override {
30
29
  func(*runtime.lock());
31
30
  }
32
- #else
33
- void invokeAsync(std::function<void()> &&func) noexcept override {
34
- func();
35
- }
36
-
37
- void invokeSync(std::function<void()> &&func) override {
38
- func();
39
- }
40
- #endif
41
31
 
42
32
  ~TestingSyncJSCallInvoker() override = default;
43
33
 
@@ -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
@@ -20,12 +20,14 @@ public struct Promise: AnyArgument {
20
20
 
21
21
  public func resolve(_ value: Any? = nil) {
22
22
  if let value = value as? AnySharedObject {
23
- let result = Conversions.convertFunctionResult(
24
- value,
25
- appContext: appContext,
26
- dynamicType: type(of: value).getDynamicType()
27
- )
28
- resolver(result)
23
+ resolver(JavaScriptSharedObjectBinding.init {
24
+ return Conversions.convertFunctionResult(
25
+ value,
26
+ appContext: appContext,
27
+ dynamicType: type(of: value).getDynamicType()
28
+ // swiftlint:disable:next force_cast
29
+ ) as! JavaScriptObject
30
+ })
29
31
  return
30
32
  }
31
33
  resolver(value)
@@ -19,7 +19,8 @@ public extension ExpoSwiftUIView {
19
19
  /**
20
20
  Returns React's children as SwiftUI views.
21
21
  */
22
- func Children() -> some View { // swiftlint:disable:this identifier_name
22
+ // swiftlint:disable:next identifier_name
23
+ func Children() -> ForEach<[any ExpoSwiftUI.AnyChild], ObjectIdentifier, AnyView> {
23
24
  ForEach(props.children ?? [], id: \.id) { child in
24
25
  let view: any View = child.childView
25
26
  AnyView(view)
@@ -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
  }
@@ -7,6 +7,7 @@
7
7
  #import <ExpoModulesCore/EXJSIConversions.h>
8
8
  #import <ExpoModulesCore/EXJavaScriptValue.h>
9
9
  #import <ExpoModulesCore/EXJavaScriptRuntime.h>
10
+ #import <ExpoModulesCore/EXJavaScriptSharedObjectBinding.h>
10
11
 
11
12
  namespace expo {
12
13
 
@@ -78,6 +79,9 @@ jsi::Value convertObjCObjectToJSIValue(jsi::Runtime &runtime, id value)
78
79
  if ([value isKindOfClass:[EXJavaScriptWeakObject class]]) {
79
80
  return jsi::Value(runtime, *[[(EXJavaScriptWeakObject *)value lock] get]);
80
81
  }
82
+ if ([value isKindOfClass:[EXJavaScriptSharedObjectBinding class]]) {
83
+ return jsi::Value(runtime, *[[(EXJavaScriptSharedObjectBinding *)value get] get]);
84
+ }
81
85
  if ([value isKindOfClass:[NSString class]]) {
82
86
  return convertNSStringToJSIString(runtime, (NSString *)value);
83
87
  } else if ([value isKindOfClass:[NSNumber class]]) {
@@ -14,7 +14,7 @@
14
14
  #import <ExpoModulesCore/EXJSIConversions.h>
15
15
  #import <ExpoModulesCore/SharedObject.h>
16
16
  #import <ExpoModulesCore/Swift.h>
17
- #import <ExpoModulesCore/TestingSyncJSCallInvoker.h>
17
+ #import <ExpoModulesCore/TestingJSCallInvoker.h>
18
18
 
19
19
  @implementation EXJavaScriptRuntime {
20
20
  std::shared_ptr<jsi::Runtime> _runtime;
@@ -45,7 +45,7 @@
45
45
  #else
46
46
  _runtime = jsc::makeJSCRuntime();
47
47
  #endif
48
- _jsCallInvoker = std::make_shared<expo::TestingSyncJSCallInvoker>(_runtime);
48
+ _jsCallInvoker = std::make_shared<expo::TestingJSCallInvoker>(_runtime);
49
49
  }
50
50
  return self;
51
51
  }
@@ -0,0 +1,25 @@
1
+ // Copyright 2023-present 650 Industries. All rights reserved.
2
+
3
+ #import <Foundation/Foundation.h>
4
+ #import <ExpoModulesCore/EXJavaScriptRuntime.h>
5
+
6
+ NS_ASSUME_NONNULL_BEGIN
7
+
8
+ typedef EXJavaScriptObject * _Nonnull (^EXJavaScriptObjectBindingGetter)(void);
9
+
10
+ NS_SWIFT_NAME(JavaScriptSharedObjectBinding)
11
+ @interface EXJavaScriptSharedObjectBinding : NSObject
12
+
13
+ @property (nonatomic, copy) EXJavaScriptObjectBindingGetter getter;
14
+
15
+ - (instancetype)initWithGetter:(EXJavaScriptObjectBindingGetter)getter
16
+ NS_DESIGNATED_INITIALIZER
17
+ NS_SWIFT_NAME(init(getter:));
18
+
19
+ - (instancetype)init NS_UNAVAILABLE;
20
+
21
+ - (EXJavaScriptObject *)get;
22
+
23
+ @end
24
+
25
+ NS_ASSUME_NONNULL_END
@@ -0,0 +1,24 @@
1
+ // Copyright 2025-present 650 Industries. All rights reserved.
2
+
3
+ #import <ExpoModulesCore/EXJSIConversions.h>
4
+ #import <ExpoModulesCore/EXJavaScriptSharedObjectBinding.h>
5
+
6
+ /**
7
+ A wrapper around a SharedObject getter – The getter is a Swift lambda that creates the JS object and registers the pair in registry.
8
+ Needed to make sure the registration happens on the correct thread when called from inside EXJSIConversions.
9
+ */
10
+ @implementation EXJavaScriptSharedObjectBinding
11
+
12
+ - (nonnull instancetype)initWithGetter:(EXJavaScriptObjectBindingGetter)getter
13
+ {
14
+ self.getter = getter;
15
+ return self;
16
+ }
17
+
18
+ - (EXJavaScriptObject *)get
19
+ {
20
+ auto obj = self.getter();
21
+ return obj;
22
+ }
23
+
24
+ @end
@@ -0,0 +1,14 @@
1
+ // Copyright 2023-present 650 Industries. All rights reserved.
2
+
3
+ #pragma once
4
+
5
+ #ifdef __cplusplus
6
+
7
+ #include <functional>
8
+
9
+ class MainThreadInvoker {
10
+ public:
11
+ static void invokeOnMainThread(const std::function<void()> task);
12
+ };
13
+
14
+ #endif // __cplusplus
@@ -0,0 +1,19 @@
1
+ // Copyright 2023-present 650 Industries. All rights reserved.
2
+
3
+ #ifdef __cplusplus
4
+
5
+ #import <ExpoModulesCore/MainThreadInvoker.h>
6
+ #import <Foundation/Foundation.h>
7
+
8
+ void MainThreadInvoker::invokeOnMainThread(const std::function<void()> task) {
9
+ dispatch_block_t block = [task]() {
10
+ task();
11
+ };
12
+ if ([NSThread isMainThread]) {
13
+ block();
14
+ } else {
15
+ dispatch_async(dispatch_get_main_queue(), block);
16
+ }
17
+ }
18
+
19
+ #endif // __cplusplus
@@ -0,0 +1,46 @@
1
+ // Copyright 2015-present 650 Industries. All rights reserved.
2
+
3
+ #pragma once
4
+
5
+ #ifdef __cplusplus
6
+
7
+ #include <ReactCommon/CallInvoker.h>
8
+ #include <ExpoModulesCore/MainThreadInvoker.h>
9
+
10
+ #include <jsi/jsi.h>
11
+
12
+ namespace jsi = facebook::jsi;
13
+ namespace react = facebook::react;
14
+
15
+ namespace expo {
16
+
17
+ /**
18
+ * Dummy CallInvoker.
19
+ * Async functions are invoked on the main thread on iOS.
20
+ * Used in the test environment to check the async flow.
21
+ */
22
+ class TestingJSCallInvoker : public react::CallInvoker {
23
+ public:
24
+ explicit TestingJSCallInvoker(const std::shared_ptr<jsi::Runtime>& runtime) : runtime(runtime) {}
25
+
26
+ void invokeAsync(react::CallFunc &&func) noexcept override {
27
+ auto weakRuntime = runtime;
28
+ std::function<void()> mainThreadFunc = [weakRuntime, func]() {
29
+ auto strongRuntime = weakRuntime.lock();
30
+ func(*strongRuntime);
31
+ };
32
+ MainThreadInvoker::invokeOnMainThread(mainThreadFunc);
33
+ }
34
+
35
+ void invokeSync(react::CallFunc &&func) override {
36
+ func(*runtime.lock());
37
+ }
38
+
39
+ ~TestingJSCallInvoker() override = default;
40
+
41
+ std::weak_ptr<jsi::Runtime> runtime;
42
+ };
43
+
44
+ } // namespace expo
45
+
46
+ #endif // __cplusplus