expo-modules-jsi 56.0.7 → 56.0.8

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 (49) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/CLAUDE.md +4 -0
  3. package/apple/Package.swift +15 -11
  4. package/apple/Sources/ExpoModulesJSI/Contexts/CleanupContext.swift +2 -4
  5. package/apple/Sources/ExpoModulesJSI/Contexts/HostFunctionContext.swift +1 -3
  6. package/apple/Sources/ExpoModulesJSI/Contexts/HostObjectContext.swift +1 -3
  7. package/apple/Sources/ExpoModulesJSI/Extensions/Task+immediate.swift +2 -0
  8. package/apple/Sources/ExpoModulesJSI/Protocols/JSIRepresentable.swift +17 -14
  9. package/apple/Sources/ExpoModulesJSI/Protocols/JavaScriptRepresentable.swift +3 -9
  10. package/apple/Sources/ExpoModulesJSI/Protocols/JavaScriptThrowable.swift +21 -27
  11. package/apple/Sources/ExpoModulesJSI/Protocols/JavaScriptType.swift +10 -18
  12. package/apple/Sources/ExpoModulesJSI/Runtime/JavaScriptActor.swift +22 -41
  13. package/apple/Sources/ExpoModulesJSI/Runtime/JavaScriptNativeState.swift +7 -15
  14. package/apple/Sources/ExpoModulesJSI/Runtime/JavaScriptPropNameID.swift +5 -15
  15. package/apple/Sources/ExpoModulesJSI/Runtime/JavaScriptRef.swift +21 -43
  16. package/apple/Sources/ExpoModulesJSI/Runtime/JavaScriptRuntime.swift +152 -202
  17. package/apple/Sources/ExpoModulesJSI/Runtime/JavaScriptValuesBuffer.swift +38 -41
  18. package/apple/Sources/ExpoModulesJSI/Runtime/Values/JavaScriptArray.swift +340 -381
  19. package/apple/Sources/ExpoModulesJSI/Runtime/Values/JavaScriptArrayBuffer.swift +9 -21
  20. package/apple/Sources/ExpoModulesJSI/Runtime/Values/JavaScriptBigInt.swift +162 -190
  21. package/apple/Sources/ExpoModulesJSI/Runtime/Values/JavaScriptError.swift +12 -15
  22. package/apple/Sources/ExpoModulesJSI/Runtime/Values/JavaScriptFunction.swift +23 -27
  23. package/apple/Sources/ExpoModulesJSI/Runtime/Values/JavaScriptObject.swift +175 -207
  24. package/apple/Sources/ExpoModulesJSI/Runtime/Values/JavaScriptPromise.swift +22 -24
  25. package/apple/Sources/ExpoModulesJSI/Runtime/Values/JavaScriptTypedArray.swift +34 -49
  26. package/apple/Sources/ExpoModulesJSI/Runtime/Values/JavaScriptValue.swift +122 -176
  27. package/apple/Sources/ExpoModulesJSI/Runtime/Values/JavaScriptWeakObject.swift +6 -14
  28. package/apple/Sources/ExpoModulesJSI/Utilities/ErrorHandling.swift +12 -20
  29. package/apple/Sources/ExpoModulesJSI/Utilities/Errors.swift +10 -22
  30. package/apple/Sources/ExpoModulesJSI/Utilities/NonisolatedUnsafeVar.swift +2 -4
  31. package/apple/Sources/ExpoModulesJSI-Cxx/include/JSIUtils.h +11 -0
  32. package/apple/Tests/JavaScriptActorTests.swift +3 -3
  33. package/apple/Tests/JavaScriptArrayBufferTests.swift +1 -1
  34. package/apple/Tests/JavaScriptArrayTests.swift +6 -4
  35. package/apple/Tests/JavaScriptBigIntTests.swift +20 -20
  36. package/apple/Tests/JavaScriptErrorTests.swift +15 -11
  37. package/apple/Tests/JavaScriptFunctionTests.swift +26 -26
  38. package/apple/Tests/JavaScriptNativeStateTests.swift +1 -1
  39. package/apple/Tests/JavaScriptObjectTests.swift +25 -13
  40. package/apple/Tests/JavaScriptPromiseTests.swift +56 -28
  41. package/apple/Tests/JavaScriptRefTests.swift +1 -1
  42. package/apple/Tests/JavaScriptRuntimeTests.swift +93 -60
  43. package/apple/Tests/JavaScriptTypedArrayTests.swift +20 -14
  44. package/apple/Tests/JavaScriptValueTests.swift +1 -1
  45. package/apple/Tests/JavaScriptValuesBufferTests.swift +1 -1
  46. package/apple/Tests/JavaScriptWeakObjectTests.swift +1 -1
  47. package/apple/scripts/build-xcframework.sh +96 -13
  48. package/apple/scripts/xcframework-helpers.sh +4 -0
  49. package/package.json +4 -2
@@ -1,79 +1,66 @@
1
1
  // Copyright 2025-present 650 Industries. All rights reserved.
2
2
 
3
+ internal import ExpoModulesJSI_Cxx
3
4
  import Foundation
4
-
5
5
  internal import jsi
6
- internal import ExpoModulesJSI_Cxx
7
-
8
- /**
9
- A Swift wrapper around a JavaScript runtime. Provides access to a JavaScript execution environment, allowing you to evaluate
10
- JavaScript code, create and manipulate JavaScript objects, functions, and values, and bridge between Swift and JavaScript.
11
6
 
12
- ## Threading
13
-
14
- JavaScript runtimes are single-threaded. All operations must be performed on the JavaScript
15
- thread. Use `schedule()` or `execute()` methods to safely run code on the correct thread.
16
- The runtime uses `@JavaScriptActor` to enforce thread safety at compile time.
17
-
18
- ## Lifecycle
19
-
20
- The runtime maintains a weak reference pattern for values, objects, and arrays to prevent
21
- retain cycles. Ensure the runtime remains alive while any derived JavaScript objects are in use.
22
- */
7
+ /// A Swift wrapper around a JavaScript runtime. Provides access to a JavaScript execution environment, allowing you to evaluate
8
+ /// JavaScript code, create and manipulate JavaScript objects, functions, and values, and bridge between Swift and JavaScript.
9
+ ///
10
+ /// ## Threading
11
+ ///
12
+ /// JavaScript runtimes are single-threaded. All operations must be performed on the JavaScript
13
+ /// thread. Use `schedule()` or `execute()` methods to safely run code on the correct thread.
14
+ /// The runtime uses `@JavaScriptActor` to enforce thread safety at compile time.
15
+ ///
16
+ /// ## Lifecycle
17
+ ///
18
+ /// The runtime maintains a weak reference pattern for values, objects, and arrays to prevent
19
+ /// retain cycles. Ensure the runtime remains alive while any derived JavaScript objects are in use.
23
20
  open class JavaScriptRuntime: Equatable, @unchecked Sendable {
24
- /**
25
- The underlying JSI runtime this `JavaScriptRuntime` points to, exposed as
26
- `IRuntime` the abstract base interface that virtually all JSI value/object/
27
- function methods take (`Value::getString`, `Object::setProperty`,
28
- `Function::call`, …) since RN 0.86 split the API. Stored as the upcast result
29
- of `runtimePointee` because Swift's C++ interop does not auto-upcast between
30
- two `SwiftImportAs: reference` types.
31
-
32
- Use ``runtimePointee`` instead when you specifically need a `jsi::Runtime&`
33
- (e.g. constructing an `expo.RuntimeScheduler` whose binding lookup is typed on
34
- `Runtime&` upstream).
35
-
36
- Note that `facebook.jsi.IRuntime` and `facebook.jsi.Runtime` are imported as
37
- reference types so for the Swift compiler they are treated like classes.
38
- This is important because they:
39
- - are abstract classes with many virtual methods. Swift/C++ interop does not support calling pure virtual methods on value types.
40
- - are non-copyable. As value types, we would have to "borrow" them from React Native in an unsafe manner.
41
- */
21
+ /// The underlying JSI runtime this `JavaScriptRuntime` points to, exposed as
22
+ /// `IRuntime` the abstract base interface that virtually all JSI value/object/
23
+ /// function methods take (`Value::getString`, `Object::setProperty`,
24
+ /// `Function::call`, …) since RN 0.86 split the API. Stored as the upcast result
25
+ /// of `runtimePointee` because Swift's C++ interop does not auto-upcast between
26
+ /// two `SwiftImportAs: reference` types.
27
+ ///
28
+ /// Use ``runtimePointee`` instead when you specifically need a `jsi::Runtime&`
29
+ /// (e.g. constructing an `expo.RuntimeScheduler` whose binding lookup is typed on
30
+ /// `Runtime&` upstream).
31
+ ///
32
+ /// Note that `facebook.jsi.IRuntime` and `facebook.jsi.Runtime` are imported as
33
+ /// reference types so for the Swift compiler they are treated like classes.
34
+ /// This is important because they:
35
+ /// - are abstract classes with many virtual methods. Swift/C++ interop does not support calling pure virtual methods on value types.
36
+ /// - are non-copyable. As value types, we would have to "borrow" them from React Native in an unsafe manner.
42
37
  internal let pointee: facebook.jsi.IRuntime
43
38
  internal let runtimePointee: facebook.jsi.Runtime
44
39
  internal let scheduler: expo.RuntimeScheduler
45
40
 
46
- /**
47
- Thread ID of the JavaScript thread, captured at construction time. Used by `isOnJavaScriptThread()`
48
- for a fast integer comparison instead of `Thread.current.name == "..."`.
49
- Assumes runtime initializers always run on the JS thread.
50
- */
41
+ /// Thread ID of the JavaScript thread, captured at construction time. Used by `isOnJavaScriptThread()`
42
+ /// for a fast integer comparison instead of `Thread.current.name == "..."`.
43
+ /// Assumes runtime initializers always run on the JS thread.
51
44
  private let jsThreadID: UInt64 = {
52
45
  var id: UInt64 = 0
53
46
  pthread_threadid_np(nil, &id)
54
47
  return id
55
48
  }()
56
49
 
57
- /**
58
- Actor for running runtime work.
59
- */
50
+ /// Actor for running runtime work.
60
51
  lazy var runtimeActor: JavaScriptRuntimeActor = JavaScriptRuntimeActor(runtime: self)
61
52
 
62
- /**
63
- Creates a runtime from the JSI runtime. The scheduler runs tasks synchronously
64
- on the caller's thread — for the React-backed runtime, use
65
- `init(unsafePointer:nativeScheduler:dispatch:)` instead.
66
- */
53
+ /// Creates a runtime from the JSI runtime. The scheduler runs tasks synchronously
54
+ /// on the caller's thread for the React-backed runtime, use
55
+ /// `init(unsafePointer:nativeScheduler:dispatch:)` instead.
67
56
  internal init(_ runtime: facebook.jsi.Runtime) {
68
57
  self.runtimePointee = runtime
69
58
  self.pointee = expo.iruntime(runtime)
70
59
  self.scheduler = expo.RuntimeScheduler()
71
60
  }
72
61
 
73
- /**
74
- Creates a standalone Hermes runtime. Scheduled tasks run synchronously —
75
- no React scheduler is wired up.
76
- */
62
+ /// Creates a standalone Hermes runtime. Scheduled tasks run synchronously —
63
+ /// no React scheduler is wired up.
77
64
  public init() {
78
65
  let runtime = expo.createHermesRuntime()
79
66
  self.runtimePointee = runtime
@@ -81,11 +68,9 @@ open class JavaScriptRuntime: Equatable, @unchecked Sendable {
81
68
  self.scheduler = expo.RuntimeScheduler()
82
69
  }
83
70
 
84
- /**
85
- Creates a runtime from a raw pointer to the underlying `facebook.jsi.Runtime`.
86
- Scheduled tasks run synchronously — for the React-backed runtime, use
87
- `init(unsafePointer:nativeScheduler:dispatch:)` instead.
88
- */
71
+ /// Creates a runtime from a raw pointer to the underlying `facebook.jsi.Runtime`.
72
+ /// Scheduled tasks run synchronously for the React-backed runtime, use
73
+ /// `init(unsafePointer:nativeScheduler:dispatch:)` instead.
89
74
  public init(unsafePointer: UnsafeMutableRawPointer) {
90
75
  let runtime = unsafeBitCast(unsafePointer, to: facebook.jsi.Runtime.self)
91
76
  self.runtimePointee = runtime
@@ -93,17 +78,15 @@ open class JavaScriptRuntime: Equatable, @unchecked Sendable {
93
78
  self.scheduler = expo.RuntimeScheduler()
94
79
  }
95
80
 
96
- /**
97
- Creates a runtime bound to a host-provided React `RuntimeScheduler`. Calls to
98
- `schedule(...)` / `.execute(...)` dispatch through `dispatch`, which the host
99
- implements against the real `react::RuntimeScheduler`. This is the path the
100
- React Native factory uses.
101
-
102
- - `unsafePointer`: raw pointer to the underlying `facebook::jsi::Runtime`.
103
- - `scheduler`: raw pointer to the `react::RuntimeScheduler` instance.
104
- - `dispatch`: raw pointer to a C function with signature
105
- `void (*)(void *scheduler, int priority, void (^callback)())`.
106
- */
81
+ /// Creates a runtime bound to a host-provided React `RuntimeScheduler`. Calls to
82
+ /// `schedule(...)` / `.execute(...)` dispatch through `dispatch`, which the host
83
+ /// implements against the real `react::RuntimeScheduler`. This is the path the
84
+ /// React Native factory uses.
85
+ ///
86
+ /// - `unsafePointer`: raw pointer to the underlying `facebook::jsi::Runtime`.
87
+ /// - `scheduler`: raw pointer to the `react::RuntimeScheduler` instance.
88
+ /// - `dispatch`: raw pointer to a C function with signature
89
+ /// `void (*)(void *scheduler, int priority, void (^callback)())`.
107
90
  public init(
108
91
  unsafePointer: UnsafeMutableRawPointer,
109
92
  scheduler: UnsafeMutableRawPointer,
@@ -116,34 +99,26 @@ open class JavaScriptRuntime: Equatable, @unchecked Sendable {
116
99
  self.scheduler = expo.RuntimeScheduler(scheduler, fn)
117
100
  }
118
101
 
119
- /**
120
- Provides scoped access to a raw pointer to the underlying `facebook.jsi.Runtime`.
121
- The pointer is valid only for the duration of the closure and must not be stored or escaped.
122
- */
102
+ /// Provides scoped access to a raw pointer to the underlying `facebook.jsi.Runtime`.
103
+ /// The pointer is valid only for the duration of the closure and must not be stored or escaped.
123
104
  public func withUnsafePointee<R>(_ body: (UnsafeMutableRawPointer) throws -> R) rethrows -> R {
124
105
  return try body(Unmanaged<facebook.jsi.Runtime>.passUnretained(runtimePointee).toOpaque())
125
106
  }
126
107
 
127
- /**
128
- Returns the runtime `global` object.
129
- */
108
+ /// Returns the runtime `global` object.
130
109
  public func global() -> JavaScriptObject {
131
110
  return JavaScriptObject(self, pointee.global())
132
111
  }
133
112
 
134
113
  // MARK: - Creating objects
135
114
 
136
- /**
137
- Creates a plain JavaScript object.
138
- */
115
+ /// Creates a plain JavaScript object.
139
116
  public func createObject() -> JavaScriptObject {
140
117
  return JavaScriptObject(self, facebook.jsi.Object(pointee))
141
118
  }
142
119
 
143
- /**
144
- Creates a new JavaScript object, using the provided object as the prototype.
145
- Calls `Object.create(prototype)` under the hood.
146
- */
120
+ /// Creates a new JavaScript object, using the provided object as the prototype.
121
+ /// Calls `Object.create(prototype)` under the hood.
147
122
  public func createObject(prototype: borrowing JavaScriptObject) -> JavaScriptObject {
148
123
  return try! global()
149
124
  .getPropertyAsObject("Object")
@@ -152,16 +127,14 @@ open class JavaScriptRuntime: Equatable, @unchecked Sendable {
152
127
  .getObject()
153
128
  }
154
129
 
155
- /**
156
- Creates a JavaScript host object with given implementations for property getter, property setter, property names getter and dealloc.
157
-
158
- Errors thrown from `get` or `set` propagate to JavaScript as a thrown `Error`. Conform
159
- the thrown type to `JavaScriptThrowable` to control the resulting `message` and `code`.
160
-
161
- Pass `nil` for `set` to make the host object read-only assignment from JavaScript
162
- then throws an `Error` whose message names the property and explains how to make it
163
- writable. `getPropertyNames` and `dealloc` default to no-ops.
164
- */
130
+ /// Creates a JavaScript host object with given implementations for property getter, property setter, property names getter and dealloc.
131
+ ///
132
+ /// Errors thrown from `get` or `set` propagate to JavaScript as a thrown `Error`. Conform
133
+ /// the thrown type to `JavaScriptThrowable` to control the resulting `message` and `code`.
134
+ ///
135
+ /// Pass `nil` for `set` to make the host object read-only — assignment from JavaScript
136
+ /// then throws an `Error` whose message names the property and explains how to make it
137
+ /// writable. `getPropertyNames` and `dealloc` default to no-ops.
165
138
  public func createHostObject(
166
139
  get: @escaping @JavaScriptActor (_ propertyName: String) throws -> JavaScriptValue,
167
140
  set: (@JavaScriptActor (_ propertyName: String, _ value: JavaScriptValue) throws -> Void)? = nil,
@@ -182,7 +155,9 @@ open class JavaScriptRuntime: Equatable, @unchecked Sendable {
182
155
  }
183
156
  }
184
157
 
185
- func setter(context: UnsafeMutableRawPointer, propertyName: UnsafePointer<CChar>, valuePointer: UnsafeMutableRawPointer) {
158
+ func setter(
159
+ context: UnsafeMutableRawPointer, propertyName: UnsafePointer<CChar>, valuePointer: UnsafeMutableRawPointer
160
+ ) {
186
161
  let context = Unmanaged<HostObjectContext>.fromOpaque(context).takeUnretainedValue()
187
162
 
188
163
  guard let runtime = context.runtime else {
@@ -236,10 +211,12 @@ open class JavaScriptRuntime: Equatable, @unchecked Sendable {
236
211
  }
237
212
  }
238
213
 
239
- let context = Unmanaged.passRetained(HostObjectContext(runtime: self, get, set, getPropertyNames, dealloc)).toOpaque()
214
+ let context = Unmanaged.passRetained(HostObjectContext(runtime: self, get, set, getPropertyNames, dealloc))
215
+ .toOpaque()
240
216
  // Pass a null setter to C++ when the Swift setter is nil so that JS assignment
241
217
  // raises a `jsi::JSError` directly, without crossing the Swift boundary.
242
- let callbacks = expo.HostObjectCallbacks(context, getter, set == nil ? nil : setter, propertyNamesGetter, deallocate)
218
+ let callbacks = expo.HostObjectCallbacks(
219
+ context, getter, set == nil ? nil : setter, propertyNamesGetter, deallocate)
243
220
  let hostObject = expo.HostObject.makeObject(pointee, consume callbacks)
244
221
 
245
222
  return JavaScriptObject(self, hostObject)
@@ -247,19 +224,17 @@ open class JavaScriptRuntime: Equatable, @unchecked Sendable {
247
224
 
248
225
  // MARK: - Creating array buffers
249
226
 
250
- /**
251
- Creates a new array buffer of the given size with zero-initialized memory.
252
- */
227
+ /// Creates a new array buffer of the given size with zero-initialized memory.
253
228
  public func createArrayBuffer(size: Int) -> JavaScriptArrayBuffer {
254
229
  let jsiArrayBuffer = expo.createArrayBuffer(pointee, size)
255
230
  return JavaScriptArrayBuffer(self, jsiArrayBuffer)
256
231
  }
257
232
 
258
- /**
259
- Creates a new array buffer that wraps the given native data pointer.
260
- The cleanup closure is called when the array buffer is garbage collected.
261
- */
262
- public func createArrayBuffer(data: UnsafeMutablePointer<UInt8>, size: Int, cleanup: @escaping @Sendable () -> Void) -> JavaScriptArrayBuffer {
233
+ /// Creates a new array buffer that wraps the given native data pointer.
234
+ /// The cleanup closure is called when the array buffer is garbage collected.
235
+ public func createArrayBuffer(data: UnsafeMutablePointer<UInt8>, size: Int, cleanup: @escaping @Sendable () -> Void)
236
+ -> JavaScriptArrayBuffer
237
+ {
263
238
  let context = Unmanaged.passRetained(CleanupContext(cleanup)).toOpaque()
264
239
  let jsiArrayBuffer = expo.createArrayBuffer(pointee, data, size, context) { context in
265
240
  Unmanaged<CleanupContext>.fromOpaque(context).release()
@@ -269,28 +244,26 @@ open class JavaScriptRuntime: Equatable, @unchecked Sendable {
269
244
 
270
245
  // MARK: - Creating arrays
271
246
 
272
- /**
273
- Creates a new Array instance.
274
- */
247
+ /// Creates a new Array instance.
275
248
  public func createArray(length: Int = 0) -> JavaScriptArray {
276
249
  return JavaScriptArray(self, facebook.jsi.Array(pointee, length))
277
250
  }
278
251
 
279
252
  // MARK: - Creating functions
280
253
 
281
- /**
282
- Type of the closure that is passed to the `createFunction` function.
283
- */
284
- public typealias SyncFunctionClosure = @JavaScriptActor (
285
- _ this: JavaScriptValue,
286
- _ arguments: consuming JavaScriptValuesBuffer
287
- ) throws -> JavaScriptValue
288
-
289
- /**
290
- Creates a class with the given name and native constructor.
291
- */
254
+ /// Type of the closure that is passed to the `createFunction` function.
255
+ public typealias SyncFunctionClosure =
256
+ @JavaScriptActor (
257
+ _ this: JavaScriptValue,
258
+ _ arguments: consuming JavaScriptValuesBuffer
259
+ ) throws -> JavaScriptValue
260
+
261
+ /// Creates a class with the given name and native constructor.
292
262
  @JavaScriptActor
293
- public func createClass(name: String, inheriting baseClass: consuming JavaScriptFunction? = nil, _ constructor: @escaping SyncFunctionClosure) throws -> JavaScriptFunction {
263
+ public func createClass(
264
+ name: String, inheriting baseClass: consuming JavaScriptFunction? = nil,
265
+ _ constructor: @escaping SyncFunctionClosure
266
+ ) throws -> JavaScriptFunction {
294
267
  // Host functions are not standard functions, thus cannot be used as class constructors.
295
268
  // We're creating one by evaluating a script that calls a "native constructor" that is a host function.
296
269
  let nativeConstructorKey = "__native_constructor__"
@@ -300,7 +273,9 @@ open class JavaScriptRuntime: Equatable, @unchecked Sendable {
300
273
  throw InvalidIdentifierError(identifier: name)
301
274
  }
302
275
 
303
- let klassValue = try eval(label: "\(name).\(nativeConstructorKey)", "(function \(name)(...args) { return this.\(nativeConstructorKey)(...args); })")
276
+ let klassValue = try eval(
277
+ label: "\(name).\(nativeConstructorKey)",
278
+ "(function \(name)(...args) { return this.\(nativeConstructorKey)(...args); })")
304
279
  let klassObject = klassValue.getObject()
305
280
 
306
281
  // Create a host function that is called by the constructor
@@ -309,7 +284,7 @@ open class JavaScriptRuntime: Equatable, @unchecked Sendable {
309
284
  }
310
285
 
311
286
  // Set native constructor as read-only, non-configurable, non-enumerable, non-writable property.
312
- let prototype = klassObject.getPropertyAsObject("prototype")
287
+ let prototype = try klassObject.getPropertyAsObject("prototype")
313
288
  prototype.defineProperty(nativeConstructorKey, value: nativeConstructor)
314
289
 
315
290
  // If the base class is provided, set the inherited prototype.
@@ -324,11 +299,9 @@ open class JavaScriptRuntime: Equatable, @unchecked Sendable {
324
299
  return klassValue.getFunction()
325
300
  }
326
301
 
327
- /**
328
- Creates a synchronous host function that runs the given closure when it's called.
329
- The value returned by the closure is synchronously returned to JS.
330
- - Returns: A JavaScript function represented as a `JavaScriptFunction`.
331
- */
302
+ /// Creates a synchronous host function that runs the given closure when it's called.
303
+ /// The value returned by the closure is synchronously returned to JS.
304
+ /// - Returns: A JavaScript function represented as a `JavaScriptFunction`.
332
305
  @JavaScriptActor
333
306
  public func createFunction(_ name: String, _ function: sending @escaping SyncFunctionClosure) -> JavaScriptFunction {
334
307
  let closure = createFunctionClosure(runtime: self, name: name, function)
@@ -337,11 +310,9 @@ open class JavaScriptRuntime: Equatable, @unchecked Sendable {
337
310
  return JavaScriptFunction(self, hostFunction)
338
311
  }
339
312
 
340
- /**
341
- Creates a synchronous anonymous host function that runs the given closure when it's called.
342
- The value returned by the closure is synchronously returned to JS.
343
- - Returns: A JavaScript function represented as a `JavaScriptFunction`.
344
- */
313
+ /// Creates a synchronous anonymous host function that runs the given closure when it's called.
314
+ /// The value returned by the closure is synchronously returned to JS.
315
+ /// - Returns: A JavaScript function represented as a `JavaScriptFunction`.
345
316
  @JavaScriptActor
346
317
  public func createFunction(_ function: sending @escaping SyncFunctionClosure) -> JavaScriptFunction {
347
318
  let closure = createFunctionClosure(runtime: self, name: nil, function)
@@ -350,24 +321,23 @@ open class JavaScriptRuntime: Equatable, @unchecked Sendable {
350
321
  return JavaScriptFunction(self, hostFunction)
351
322
  }
352
323
 
353
- /**
354
- Type of the closure that is passed to the `createAsyncFunction` function.
355
- It is invoked from asynchronous context, so it can await and call other asynchronous functions.
356
- */
357
- public typealias AsyncFunctionClosure = @JavaScriptActor (
358
- _ this: JavaScriptValue,
359
- _ arguments: consuming JavaScriptValuesBuffer,
360
- ) async throws -> JavaScriptValue
361
-
362
- /**
363
- Creates an asynchronous host function that runs given block when it's called.
364
- The value returned by the closure is returned to JS asynchronously.
365
- - Returns: A JavaScript function represented as a `JavaScriptFunction` that returns a promise.
366
- */
324
+ /// Type of the closure that is passed to the `createAsyncFunction` function.
325
+ /// It is invoked from asynchronous context, so it can await and call other asynchronous functions.
326
+ public typealias AsyncFunctionClosure =
327
+ @JavaScriptActor (
328
+ _ this: JavaScriptValue,
329
+ _ arguments: consuming JavaScriptValuesBuffer,
330
+ ) async throws -> JavaScriptValue
331
+
332
+ /// Creates an asynchronous host function that runs given block when it's called.
333
+ /// The value returned by the closure is returned to JS asynchronously.
334
+ /// - Returns: A JavaScript function represented as a `JavaScriptFunction` that returns a promise.
367
335
  @JavaScriptActor
368
- public func createAsyncFunction(_ name: String, _ function: sending @escaping AsyncFunctionClosure) -> JavaScriptFunction {
336
+ public func createAsyncFunction(_ name: String, _ function: sending @escaping AsyncFunctionClosure)
337
+ -> JavaScriptFunction
338
+ {
369
339
  return createFunction(name) { this, arguments in
370
- let promise = JavaScriptPromise(self)
340
+ let promise = try JavaScriptPromise(self)
371
341
 
372
342
  // Arguments buffer needs to be copied to ensure safe async access.
373
343
  let argumentsRef = arguments.copy().ref()
@@ -390,18 +360,17 @@ open class JavaScriptRuntime: Equatable, @unchecked Sendable {
390
360
 
391
361
  // MARK: - Runtime execution
392
362
 
393
- /**
394
- Whether the runtime scheduler can dispatch work asynchronously to the JS thread.
395
- Returns false for standalone runtimes (e.g. in tests) where scheduled tasks run synchronously.
396
- */
363
+ /// Whether the runtime scheduler can dispatch work asynchronously to the JS thread.
364
+ /// Returns false for standalone runtimes (e.g. in tests) where scheduled tasks run synchronously.
397
365
  public var supportsAsyncScheduling: Bool {
398
366
  return scheduler.supportsAsyncScheduling()
399
367
  }
400
368
 
401
- /**
402
- Schedules a closure to be executed with granted synchronized access to the runtime.
403
- */
404
- public func schedule(priority: SchedulerPriority = .normal, @_implicitSelfCapture _ closure: @escaping @JavaScriptActor () -> sending Void) -> Void {
369
+ /// Schedules a closure to be executed with granted synchronized access to the runtime.
370
+ public func schedule(
371
+ priority: SchedulerPriority = .normal,
372
+ @_implicitSelfCapture _ closure: @escaping @JavaScriptActor () -> sending Void
373
+ ) {
405
374
  let cxxPriority = expo.RuntimeScheduler.Priority(rawValue: priority.rawValue) ?? .NormalPriority
406
375
  scheduler.scheduleTask(cxxPriority) {
407
376
  JavaScriptActor.assumeIsolated(closure)
@@ -411,7 +380,7 @@ open class JavaScriptRuntime: Equatable, @unchecked Sendable {
411
380
  public func schedule(
412
381
  priority: SchedulerPriority = .normal,
413
382
  @_implicitSelfCapture _ closure: @escaping @JavaScriptActor () async throws -> Void
414
- ) -> Void {
383
+ ) {
415
384
  schedule(priority: priority) {
416
385
  Task.immediate_polyfill {
417
386
  try await closure()
@@ -419,13 +388,13 @@ open class JavaScriptRuntime: Equatable, @unchecked Sendable {
419
388
  }
420
389
  }
421
390
 
422
- /**
423
- Synchronously executes a closure on the JavaScript runtime thread, blocking the current thread until completion.
424
- Not available in async contexts to prevent blocking the cooperative thread pool.
425
- */
391
+ /// Synchronously executes a closure on the JavaScript runtime thread, blocking the current thread until completion.
392
+ /// Not available in async contexts to prevent blocking the cooperative thread pool.
426
393
  @available(*, noasync)
427
394
  @discardableResult
428
- public func execute<R: Sendable>(@_implicitSelfCapture _ closure: @escaping @JavaScriptActor () throws -> R) throws -> sending R {
395
+ public func execute<R: Sendable>(@_implicitSelfCapture _ closure: @escaping @JavaScriptActor () throws -> R) throws
396
+ -> sending R
397
+ {
429
398
  if isOnJavaScriptThread() {
430
399
  return try JavaScriptActor.assumeIsolated(closure)
431
400
  }
@@ -460,10 +429,8 @@ open class JavaScriptRuntime: Equatable, @unchecked Sendable {
460
429
  return try result.get()
461
430
  }
462
431
 
463
- /**
464
- Synchronously executes an async closure on the JavaScript runtime thread, blocking the current thread until completion.
465
- Not available in async contexts to prevent blocking the cooperative thread pool.
466
- */
432
+ /// Synchronously executes an async closure on the JavaScript runtime thread, blocking the current thread until completion.
433
+ /// Not available in async contexts to prevent blocking the cooperative thread pool.
467
434
  @available(*, noasync)
468
435
  @discardableResult
469
436
  public func execute<R: Sendable>(
@@ -475,7 +442,7 @@ open class JavaScriptRuntime: Equatable, @unchecked Sendable {
475
442
  // to work around a Swift 6.2.3 compiler bug.
476
443
  let callerRunLoop = NonisolatedUnsafeVar(CFRunLoopGetCurrent())
477
444
 
478
- func body() -> Void {
445
+ func body() {
479
446
  Task.immediate_polyfill(priority: .high) {
480
447
  do {
481
448
  result.value = .success(try await closure())
@@ -503,9 +470,7 @@ open class JavaScriptRuntime: Equatable, @unchecked Sendable {
503
470
  return try result.value.get()
504
471
  }
505
472
 
506
- /**
507
- Asynchronously executes a sync closure on the JavaScript runtime thread, awaiting its completion without blocking.
508
- */
473
+ /// Asynchronously executes a sync closure on the JavaScript runtime thread, awaiting its completion without blocking.
509
474
  @discardableResult
510
475
  public func execute<R: Sendable>(
511
476
  @_implicitSelfCapture _ closure: @escaping @JavaScriptActor () throws -> R
@@ -524,9 +489,7 @@ open class JavaScriptRuntime: Equatable, @unchecked Sendable {
524
489
  }
525
490
  }
526
491
 
527
- /**
528
- Asynchronously executes an async closure on the JavaScript runtime thread, awaiting its completion without blocking.
529
- */
492
+ /// Asynchronously executes an async closure on the JavaScript runtime thread, awaiting its completion without blocking.
530
493
  @discardableResult
531
494
  public func execute<R: Sendable>(
532
495
  @_implicitSelfCapture _ closure: @escaping @JavaScriptActor () async throws -> R
@@ -547,9 +510,7 @@ open class JavaScriptRuntime: Equatable, @unchecked Sendable {
547
510
  }
548
511
  }
549
512
 
550
- /**
551
- Checks whether the function is called on the JavaScript thread.
552
- */
513
+ /// Checks whether the function is called on the JavaScript thread.
553
514
  @inline(__always)
554
515
  public final func isOnJavaScriptThread() -> Bool {
555
516
  var current: UInt64 = 0
@@ -557,18 +518,14 @@ open class JavaScriptRuntime: Equatable, @unchecked Sendable {
557
518
  return current == jsThreadID
558
519
  }
559
520
 
560
- /**
561
- Asserts whether we are on the JavaScript thread. Helpful for debugging threading issues.
562
- */
521
+ /// Asserts whether we are on the JavaScript thread. Helpful for debugging threading issues.
563
522
  @inline(__always)
564
523
  public final func assertThread(file: String = #file, function: String = #function, line: Int = #line) {
565
524
  assert(isOnJavaScriptThread(), "Function '\(function)' is not run on the JavaScript thread (\(file):\(line))")
566
525
  }
567
526
 
568
- /**
569
- Priority of the scheduled task.
570
- - Note: Keep it in sync with the equivalent C++ enum from React Native (see `SchedulerPriority.h` from `React-callinvoker`).
571
- */
527
+ /// Priority of the scheduled task.
528
+ /// - Note: Keep it in sync with the equivalent C++ enum from React Native (see `SchedulerPriority.h` from `React-callinvoker`).
572
529
  public enum SchedulerPriority: Int32 {
573
530
  case immediate = 1
574
531
  case userBlocking = 2
@@ -579,9 +536,7 @@ open class JavaScriptRuntime: Equatable, @unchecked Sendable {
579
536
 
580
537
  // MARK: - Script evaluation
581
538
 
582
- /**
583
- Evaluates given JavaScript source code.
584
- */
539
+ /// Evaluates given JavaScript source code.
585
540
  @discardableResult
586
541
  @JavaScriptActor
587
542
  public func eval(label: String? = nil, _ source: String) throws -> JavaScriptValue {
@@ -597,9 +552,7 @@ open class JavaScriptRuntime: Equatable, @unchecked Sendable {
597
552
  }
598
553
  }
599
554
 
600
- /**
601
- Evaluates the given JavaScript source code made by joining an array of strings with a newline separator.
602
- */
555
+ /// Evaluates the given JavaScript source code made by joining an array of strings with a newline separator.
603
556
  @available(*, deprecated, message: "Spread the array into arguments instead")
604
557
  @discardableResult
605
558
  @JavaScriptActor
@@ -607,18 +560,14 @@ open class JavaScriptRuntime: Equatable, @unchecked Sendable {
607
560
  try eval(label: label, lines.joined(separator: "\n"))
608
561
  }
609
562
 
610
- /**
611
- Evaluates the given JavaScript source code made by joining arguments with a newline separator.
612
- */
563
+ /// Evaluates the given JavaScript source code made by joining arguments with a newline separator.
613
564
  @discardableResult
614
565
  @JavaScriptActor
615
566
  public func eval(label: String? = nil, _ lines: String...) throws -> JavaScriptValue {
616
567
  try eval(label: label, lines.joined(separator: "\n"))
617
568
  }
618
569
 
619
- /**
620
- Evaluates given JavaScript source code in an async context. If the evaluated source returns a Promise, it awaits until the promise is resolved/rejected.
621
- */
570
+ /// Evaluates given JavaScript source code in an async context. If the evaluated source returns a Promise, it awaits until the promise is resolved/rejected.
622
571
  @discardableResult
623
572
  @JavaScriptActor
624
573
  public func evalAsync(label: String? = nil, _ source: String) async throws -> JavaScriptValue {
@@ -638,10 +587,15 @@ open class JavaScriptRuntime: Equatable, @unchecked Sendable {
638
587
  internal var propNameIdsRegistry: [String: JavaScriptPropNameID] = [:]
639
588
  }
640
589
 
641
- private func createFunctionClosure(runtime: JavaScriptRuntime, name: String? = nil, _ closure: @escaping JavaScriptRuntime.SyncFunctionClosure) -> expo.HostFunctionClosure {
590
+ private func createFunctionClosure(
591
+ runtime: JavaScriptRuntime, name: String? = nil, _ closure: @escaping JavaScriptRuntime.SyncFunctionClosure
592
+ ) -> expo.HostFunctionClosure {
642
593
  let context = Unmanaged.passRetained(HostFunctionContext(runtime: runtime, name: name, closure)).toOpaque()
643
594
 
644
- func call(context: UnsafeMutableRawPointer, thisPtr: UnsafePointer<facebook.jsi.Value>, argumentsPtr: UnsafePointer<facebook.jsi.Value>, argumentsCount: Int) -> facebook.jsi.Value {
595
+ func call(
596
+ context: UnsafeMutableRawPointer, thisPtr: UnsafePointer<facebook.jsi.Value>,
597
+ argumentsPtr: UnsafePointer<facebook.jsi.Value>, argumentsCount: Int
598
+ ) -> facebook.jsi.Value {
645
599
  let context = Unmanaged<HostFunctionContext>.fromOpaque(context).takeUnretainedValue()
646
600
 
647
601
  guard let runtime = context.runtime else {
@@ -668,14 +622,10 @@ private func createFunctionClosure(runtime: JavaScriptRuntime, name: String? = n
668
622
  // MARK: - Errors
669
623
 
670
624
  extension JavaScriptRuntime {
671
- /**
672
- Thrown when an invalid JavaScript identifier is passed to APIs that interpolate
673
- the name into evaluated JavaScript source, such as ``createClass(name:inheriting:_:)``.
674
- */
625
+ /// Thrown when an invalid JavaScript identifier is passed to APIs that interpolate
626
+ /// the name into evaluated JavaScript source, such as ``createClass(name:inheriting:_:)``.
675
627
  public struct InvalidIdentifierError: Error, CustomStringConvertible {
676
- /**
677
- The identifier string that failed validation.
678
- */
628
+ /// The identifier string that failed validation.
679
629
  public let identifier: String
680
630
 
681
631
  public var description: String {