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.
- package/CHANGELOG.md +12 -0
- package/CLAUDE.md +4 -0
- package/apple/Package.swift +15 -11
- package/apple/Sources/ExpoModulesJSI/Contexts/CleanupContext.swift +2 -4
- package/apple/Sources/ExpoModulesJSI/Contexts/HostFunctionContext.swift +1 -3
- package/apple/Sources/ExpoModulesJSI/Contexts/HostObjectContext.swift +1 -3
- package/apple/Sources/ExpoModulesJSI/Extensions/Task+immediate.swift +2 -0
- package/apple/Sources/ExpoModulesJSI/Protocols/JSIRepresentable.swift +17 -14
- package/apple/Sources/ExpoModulesJSI/Protocols/JavaScriptRepresentable.swift +3 -9
- package/apple/Sources/ExpoModulesJSI/Protocols/JavaScriptThrowable.swift +21 -27
- package/apple/Sources/ExpoModulesJSI/Protocols/JavaScriptType.swift +10 -18
- package/apple/Sources/ExpoModulesJSI/Runtime/JavaScriptActor.swift +22 -41
- package/apple/Sources/ExpoModulesJSI/Runtime/JavaScriptNativeState.swift +7 -15
- package/apple/Sources/ExpoModulesJSI/Runtime/JavaScriptPropNameID.swift +5 -15
- package/apple/Sources/ExpoModulesJSI/Runtime/JavaScriptRef.swift +21 -43
- package/apple/Sources/ExpoModulesJSI/Runtime/JavaScriptRuntime.swift +152 -202
- package/apple/Sources/ExpoModulesJSI/Runtime/JavaScriptValuesBuffer.swift +38 -41
- package/apple/Sources/ExpoModulesJSI/Runtime/Values/JavaScriptArray.swift +340 -381
- package/apple/Sources/ExpoModulesJSI/Runtime/Values/JavaScriptArrayBuffer.swift +9 -21
- package/apple/Sources/ExpoModulesJSI/Runtime/Values/JavaScriptBigInt.swift +162 -190
- package/apple/Sources/ExpoModulesJSI/Runtime/Values/JavaScriptError.swift +12 -15
- package/apple/Sources/ExpoModulesJSI/Runtime/Values/JavaScriptFunction.swift +23 -27
- package/apple/Sources/ExpoModulesJSI/Runtime/Values/JavaScriptObject.swift +175 -207
- package/apple/Sources/ExpoModulesJSI/Runtime/Values/JavaScriptPromise.swift +22 -24
- package/apple/Sources/ExpoModulesJSI/Runtime/Values/JavaScriptTypedArray.swift +34 -49
- package/apple/Sources/ExpoModulesJSI/Runtime/Values/JavaScriptValue.swift +122 -176
- package/apple/Sources/ExpoModulesJSI/Runtime/Values/JavaScriptWeakObject.swift +6 -14
- package/apple/Sources/ExpoModulesJSI/Utilities/ErrorHandling.swift +12 -20
- package/apple/Sources/ExpoModulesJSI/Utilities/Errors.swift +10 -22
- package/apple/Sources/ExpoModulesJSI/Utilities/NonisolatedUnsafeVar.swift +2 -4
- package/apple/Sources/ExpoModulesJSI-Cxx/include/JSIUtils.h +11 -0
- package/apple/Tests/JavaScriptActorTests.swift +3 -3
- package/apple/Tests/JavaScriptArrayBufferTests.swift +1 -1
- package/apple/Tests/JavaScriptArrayTests.swift +6 -4
- package/apple/Tests/JavaScriptBigIntTests.swift +20 -20
- package/apple/Tests/JavaScriptErrorTests.swift +15 -11
- package/apple/Tests/JavaScriptFunctionTests.swift +26 -26
- package/apple/Tests/JavaScriptNativeStateTests.swift +1 -1
- package/apple/Tests/JavaScriptObjectTests.swift +25 -13
- package/apple/Tests/JavaScriptPromiseTests.swift +56 -28
- package/apple/Tests/JavaScriptRefTests.swift +1 -1
- package/apple/Tests/JavaScriptRuntimeTests.swift +93 -60
- package/apple/Tests/JavaScriptTypedArrayTests.swift +20 -14
- package/apple/Tests/JavaScriptValueTests.swift +1 -1
- package/apple/Tests/JavaScriptValuesBufferTests.swift +1 -1
- package/apple/Tests/JavaScriptWeakObjectTests.swift +1 -1
- package/apple/scripts/build-xcframework.sh +96 -13
- package/apple/scripts/xcframework-helpers.sh +4 -0
- package/package.json +4 -2
|
@@ -1,98 +1,90 @@
|
|
|
1
|
-
internal import jsi
|
|
2
1
|
internal import ExpoModulesJSI_Cxx
|
|
2
|
+
internal import jsi
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
to the underlying JavaScript array and provides Swift-friendly APIs for common array operations.
|
|
8
|
-
*/
|
|
4
|
+
/// A Swift representation of a JavaScript array. `JavaScriptArray` provides a bridge between JavaScript arrays
|
|
5
|
+
/// and Swift, allowing you to access and manipulate JavaScript array elements from Swift code. It maintains a reference
|
|
6
|
+
/// to the underlying JavaScript array and provides Swift-friendly APIs for common array operations.
|
|
9
7
|
public struct JavaScriptArray: JavaScriptType, ~Copyable {
|
|
10
8
|
internal weak let runtime: JavaScriptRuntime?
|
|
11
9
|
internal let pointee: facebook.jsi.Array
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
- SeeAlso: `init(_:items:)` for creating arrays with initial values
|
|
39
|
-
*/
|
|
11
|
+
/// Creates a new JavaScript array with the specified length.
|
|
12
|
+
///
|
|
13
|
+
/// This is the primary initializer for creating empty or pre-sized JavaScript arrays.
|
|
14
|
+
/// If no length is provided, an empty array is created. When a length is specified,
|
|
15
|
+
/// the array is created with that many elements, each initialized to `undefined`.
|
|
16
|
+
///
|
|
17
|
+
/// - Parameters:
|
|
18
|
+
/// - runtime: The JavaScript runtime in which to create the array
|
|
19
|
+
/// - length: The initial length of the array. Defaults to 0 (empty array).
|
|
20
|
+
///
|
|
21
|
+
/// ## Examples
|
|
22
|
+
///
|
|
23
|
+
/// ```swift
|
|
24
|
+
/// // Create an empty array
|
|
25
|
+
/// let empty = JavaScriptArray(runtime)
|
|
26
|
+
///
|
|
27
|
+
/// // Create an array with specific length (all elements are undefined)
|
|
28
|
+
/// let sized = JavaScriptArray(runtime, length: 10)
|
|
29
|
+
/// print(sized.length) // 10
|
|
30
|
+
/// print(sized[0]) // undefined
|
|
31
|
+
/// ```
|
|
32
|
+
///
|
|
33
|
+
/// - Note: This initializer creates a new JavaScript array object in the runtime's heap.
|
|
34
|
+
/// The array's length can be modified later using the `length` property.
|
|
35
|
+
/// - SeeAlso: `init(_:items:)` for creating arrays with initial values
|
|
40
36
|
public init(_ runtime: JavaScriptRuntime, length: Int = 0) {
|
|
41
37
|
self.init(runtime, facebook.jsi.Array(runtime.pointee, length))
|
|
42
38
|
}
|
|
43
39
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
object is moved into this structure and the caller's copy is invalidated.
|
|
60
|
-
*/
|
|
40
|
+
/// Creates a Swift wrapper around an existing JSI array object.
|
|
41
|
+
///
|
|
42
|
+
/// This internal initializer is used to wrap a C++ JSI `Array` object with a Swift
|
|
43
|
+
/// `JavaScriptArray` interface. It takes ownership of the provided JSI array using
|
|
44
|
+
/// Swift's consuming parameter ownership, ensuring proper move semantics.
|
|
45
|
+
///
|
|
46
|
+
/// - Parameters:
|
|
47
|
+
/// - runtime: The JavaScript runtime that owns the array
|
|
48
|
+
/// - pointee: The underlying JSI `Array` object to wrap (consumed)
|
|
49
|
+
///
|
|
50
|
+
/// - Note: This initializer is internal and used by the library's implementation to
|
|
51
|
+
/// bridge between the C++ JSI layer and Swift. It should not be called directly
|
|
52
|
+
/// by library consumers.
|
|
53
|
+
/// - Note: The `pointee` parameter uses consuming ownership, meaning the JSI array
|
|
54
|
+
/// object is moved into this structure and the caller's copy is invalidated.
|
|
61
55
|
internal init(_ runtime: JavaScriptRuntime, _ pointee: consuming facebook.jsi.Array) {
|
|
62
56
|
self.runtime = runtime
|
|
63
57
|
self.pointee = pointee
|
|
64
58
|
}
|
|
65
59
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
- SeeAlso: `init(_:items:)` for the variadic argument version
|
|
95
|
-
*/
|
|
60
|
+
/// Creates a new JavaScript array initialized with the provided array of values.
|
|
61
|
+
///
|
|
62
|
+
/// This initializer allows you to create a JavaScript array from a Swift array of
|
|
63
|
+
/// `JavaScriptValue` elements. This is particularly useful when you already have
|
|
64
|
+
/// a collection of values and want to avoid the syntactic overhead of spreading them
|
|
65
|
+
/// as variadic arguments.
|
|
66
|
+
///
|
|
67
|
+
/// - Parameters:
|
|
68
|
+
/// - runtime: The JavaScript runtime in which to create the array
|
|
69
|
+
/// - items: A Swift array of `JavaScriptValue` elements to populate the array with
|
|
70
|
+
///
|
|
71
|
+
/// ## Examples
|
|
72
|
+
///
|
|
73
|
+
/// ```swift
|
|
74
|
+
/// // Create from an existing array
|
|
75
|
+
/// let values = [JavaScriptValue.number(1), .number(2), .number(3)]
|
|
76
|
+
/// let array = JavaScriptArray(runtime, items: values)
|
|
77
|
+
///
|
|
78
|
+
/// // Create from a mapped collection
|
|
79
|
+
/// let numbers = [1, 2, 3, 4, 5]
|
|
80
|
+
/// let jsValues = numbers.map { JavaScriptValue.number(Double($0)) }
|
|
81
|
+
/// let array = JavaScriptArray(runtime, items: jsValues)
|
|
82
|
+
/// ```
|
|
83
|
+
///
|
|
84
|
+
/// - Note: Due to limitations in Swift/C++ interop with `std::initializer_list`, this
|
|
85
|
+
/// implementation creates an empty array first and then populates it element by element,
|
|
86
|
+
/// rather than using JSI's `createWithElements` method directly.
|
|
87
|
+
/// - SeeAlso: `init(_:items:)` for the variadic argument version
|
|
96
88
|
public init(_ runtime: JavaScriptRuntime, items: [JavaScriptValue]) {
|
|
97
89
|
self.init(runtime, length: items.count)
|
|
98
90
|
|
|
@@ -101,76 +93,72 @@ public struct JavaScriptArray: JavaScriptType, ~Copyable {
|
|
|
101
93
|
}
|
|
102
94
|
}
|
|
103
95
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
- SeeAlso: `init(_:items:)` for the array version
|
|
133
|
-
*/
|
|
96
|
+
/// Creates a new JavaScript array initialized with the provided values.
|
|
97
|
+
///
|
|
98
|
+
/// This convenience initializer allows you to create a JavaScript array from a variable
|
|
99
|
+
/// number of `JavaScriptValue` arguments. The array is created with the appropriate length
|
|
100
|
+
/// and populated with the provided values in order.
|
|
101
|
+
///
|
|
102
|
+
/// - Parameters:
|
|
103
|
+
/// - runtime: The JavaScript runtime in which to create the array
|
|
104
|
+
/// - items: A variadic list of `JavaScriptValue` elements to populate the array with
|
|
105
|
+
///
|
|
106
|
+
/// ## Examples
|
|
107
|
+
///
|
|
108
|
+
/// ```swift
|
|
109
|
+
/// // Create an empty array
|
|
110
|
+
/// let empty = JavaScriptArray(runtime, items: )
|
|
111
|
+
///
|
|
112
|
+
/// // Create an array with values
|
|
113
|
+
/// let numbers = JavaScriptArray(runtime, items: .number(1), .number(2), .number(3))
|
|
114
|
+
///
|
|
115
|
+
/// // Mix different value types
|
|
116
|
+
/// let mixed = JavaScriptArray(runtime,
|
|
117
|
+
/// items: .string("hello"), .number(42), .bool(true))
|
|
118
|
+
/// ```
|
|
119
|
+
///
|
|
120
|
+
/// - Note: This variadic version internally creates a Swift array and delegates to the
|
|
121
|
+
/// array-based initializer. If you already have an array of values, consider using
|
|
122
|
+
/// `init(_:items:)` directly for cleaner syntax.
|
|
123
|
+
/// - SeeAlso: `init(_:items:)` for the array version
|
|
134
124
|
public init(_ runtime: JavaScriptRuntime, items: JavaScriptValue...) {
|
|
135
125
|
self.init(runtime, items: items)
|
|
136
126
|
}
|
|
137
127
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
- SeeAlso: `init(_:items:)` for the `JavaScriptValue` array version
|
|
173
|
-
*/
|
|
128
|
+
/// Creates a new JavaScript array from variadic arguments of any types conforming to `JavaScriptRepresentable`.
|
|
129
|
+
///
|
|
130
|
+
/// This generic initializer uses Swift's parameter pack feature to accept a variable number of
|
|
131
|
+
/// arguments of potentially different types, as long as each type conforms to `JavaScriptRepresentable`.
|
|
132
|
+
/// This provides a type-safe and ergonomic way to create JavaScript arrays from Swift values without
|
|
133
|
+
/// needing to manually convert them to `JavaScriptValue` first.
|
|
134
|
+
///
|
|
135
|
+
/// - Parameters:
|
|
136
|
+
/// - runtime: The JavaScript runtime in which to create the array
|
|
137
|
+
/// - items: A variadic parameter pack of values conforming to `JavaScriptRepresentable`
|
|
138
|
+
///
|
|
139
|
+
/// ## Examples
|
|
140
|
+
///
|
|
141
|
+
/// ```swift
|
|
142
|
+
/// // Mix different Swift types directly
|
|
143
|
+
/// let array = JavaScriptArray(runtime, items: 42, "hello", true, 3.14)
|
|
144
|
+
///
|
|
145
|
+
/// // All same type works too
|
|
146
|
+
/// let numbers = JavaScriptArray(runtime, items: 1, 2, 3, 4, 5)
|
|
147
|
+
///
|
|
148
|
+
/// // Use with custom types that conform to JavaScriptRepresentable
|
|
149
|
+
/// struct Person: JavaScriptRepresentable {
|
|
150
|
+
/// let name: String
|
|
151
|
+
/// let age: Int
|
|
152
|
+
/// }
|
|
153
|
+
/// let people = [Person(name: "Alice", age: 30), Person(name: "Bob", age: 25)]
|
|
154
|
+
/// let array = JavaScriptArray(runtime, items: people[0], people[1])
|
|
155
|
+
/// ```
|
|
156
|
+
///
|
|
157
|
+
/// - Note: This initializer automatically converts each item to a `JavaScriptValue` using
|
|
158
|
+
/// its `toJavaScriptValue(in:)` method, providing compile-time type safety.
|
|
159
|
+
/// - Note: Unlike the `JavaScriptValue` variadic initializer, this version accepts heterogeneous
|
|
160
|
+
/// types directly without requiring explicit `JavaScriptValue` wrapping.
|
|
161
|
+
/// - SeeAlso: `init(_:items:)` for the `JavaScriptValue` array version
|
|
174
162
|
public init<each T: JavaScriptRepresentable>(_ runtime: JavaScriptRuntime, items: repeat each T) {
|
|
175
163
|
var length: Int = 0
|
|
176
164
|
for _ in repeat each items {
|
|
@@ -186,42 +174,40 @@ public struct JavaScriptArray: JavaScriptType, ~Copyable {
|
|
|
186
174
|
}
|
|
187
175
|
}
|
|
188
176
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
providing the same semantics as `array.length = newValue` in JavaScript.
|
|
224
|
-
*/
|
|
177
|
+
/// The length of the JavaScript array, equivalent to the `length` property in JavaScript.
|
|
178
|
+
///
|
|
179
|
+
/// This property provides direct access to the array's length, which can be both read and
|
|
180
|
+
/// modified. Changing the length affects the array size, matching JavaScript's behavior.
|
|
181
|
+
///
|
|
182
|
+
/// ## Getting the Length
|
|
183
|
+
///
|
|
184
|
+
/// Returns the current number of elements in the array:
|
|
185
|
+
///
|
|
186
|
+
/// ```swift
|
|
187
|
+
/// let array = try runtime.eval("[1, 2, 3]").getArray()
|
|
188
|
+
/// print(array.length) // 3
|
|
189
|
+
/// ```
|
|
190
|
+
///
|
|
191
|
+
/// ## Setting the Length
|
|
192
|
+
///
|
|
193
|
+
/// Modifying the length changes the array size:
|
|
194
|
+
/// - **Increasing** the length adds `undefined` elements to fill the gap
|
|
195
|
+
/// - **Decreasing** the length truncates the array, removing elements
|
|
196
|
+
///
|
|
197
|
+
/// ```swift
|
|
198
|
+
/// let array = try runtime.eval("[1, 2, 3, 4, 5]").getArray()
|
|
199
|
+
///
|
|
200
|
+
/// // Truncate the array
|
|
201
|
+
/// array.length = 3
|
|
202
|
+
/// // Array is now [1, 2, 3]
|
|
203
|
+
///
|
|
204
|
+
/// // Expand the array
|
|
205
|
+
/// array.length = 5
|
|
206
|
+
/// // Array is now [1, 2, 3, undefined, undefined]
|
|
207
|
+
/// ```
|
|
208
|
+
///
|
|
209
|
+
/// - Note: This property directly modifies the JavaScript array's `length` property,
|
|
210
|
+
/// providing the same semantics as `array.length = newValue` in JavaScript.
|
|
225
211
|
public var length: Int {
|
|
226
212
|
get {
|
|
227
213
|
guard let runtime else {
|
|
@@ -237,14 +223,12 @@ public struct JavaScriptArray: JavaScriptType, ~Copyable {
|
|
|
237
223
|
}
|
|
238
224
|
}
|
|
239
225
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
greater than or equal to the array's length
|
|
247
|
-
*/
|
|
226
|
+
/// Retrieves the value at the specified index in the array.
|
|
227
|
+
///
|
|
228
|
+
/// - Parameter index: The zero-based index of the element to retrieve
|
|
229
|
+
/// - Returns: The `JavaScriptValue` at the specified index
|
|
230
|
+
/// - Throws: `JavaScriptArray.Errors.indexOutOfRange` if the index is negative or
|
|
231
|
+
/// greater than or equal to the array's length
|
|
248
232
|
public func getValue(at index: Int) throws -> JavaScriptValue {
|
|
249
233
|
guard let runtime else {
|
|
250
234
|
FatalError.runtimeLost()
|
|
@@ -256,24 +240,20 @@ public struct JavaScriptArray: JavaScriptType, ~Copyable {
|
|
|
256
240
|
return JavaScriptValue(runtime, pointee.getValueAtIndex(runtime.pointee, index))
|
|
257
241
|
}
|
|
258
242
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
check avoids a weak-runtime load on every element on the hot path.
|
|
264
|
-
*/
|
|
243
|
+
/// Returns the value at the given index without bounds-checking. Used by the iteration
|
|
244
|
+
/// helpers (`map`, `forEach`, `reduce`, `filter`, `enumerated`) which iterate
|
|
245
|
+
/// `0..<length` and never produce an out-of-range index. Skipping the redundant bounds
|
|
246
|
+
/// check avoids a weak-runtime load on every element on the hot path.
|
|
265
247
|
internal func getValueUnchecked(at index: Int, in runtime: JavaScriptRuntime) -> JavaScriptValue {
|
|
266
248
|
return JavaScriptValue(runtime, pointee.getValueAtIndex(runtime.pointee, index))
|
|
267
249
|
}
|
|
268
250
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
- Throws: `JavaScriptArray.Errors.indexOutOfRange` if the index is out of bounds
|
|
276
|
-
*/
|
|
251
|
+
/// Sets the element at the specified index.
|
|
252
|
+
///
|
|
253
|
+
/// - Parameters:
|
|
254
|
+
/// - value: The value to set, conforming to `JavaScriptRepresentable`
|
|
255
|
+
/// - index: The zero-based index where the value should be set
|
|
256
|
+
/// - Throws: `JavaScriptArray.Errors.indexOutOfRange` if the index is out of bounds
|
|
277
257
|
public func set<T: JavaScriptRepresentable & ~Copyable>(value: borrowing T, at index: Int) throws {
|
|
278
258
|
guard let runtime else {
|
|
279
259
|
FatalError.runtimeLost()
|
|
@@ -286,42 +266,40 @@ public struct JavaScriptArray: JavaScriptType, ~Copyable {
|
|
|
286
266
|
expo.setValueAtIndex(runtime.pointee, pointee, index, jsiValue)
|
|
287
267
|
}
|
|
288
268
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
are filled with `undefined`, matching JavaScript's behavior.
|
|
324
|
-
*/
|
|
269
|
+
/// Accesses array elements by numeric index with safe, non-throwing behavior.
|
|
270
|
+
///
|
|
271
|
+
/// This subscript provides a convenient way to read and write array elements without
|
|
272
|
+
/// explicit error handling. It mimics JavaScript's array behavior by automatically
|
|
273
|
+
/// handling out-of-bounds access and dynamic resizing.
|
|
274
|
+
///
|
|
275
|
+
/// - Parameter index: The zero-based index of the element to access or modify
|
|
276
|
+
/// - Returns: The `JavaScriptValue` at the specified index, or `undefined` if the index
|
|
277
|
+
/// is out of range
|
|
278
|
+
///
|
|
279
|
+
/// ## Getting Values
|
|
280
|
+
///
|
|
281
|
+
/// Returns `undefined` if the index is out of bounds (no error thrown):
|
|
282
|
+
///
|
|
283
|
+
/// ```swift
|
|
284
|
+
/// let array = try runtime.eval("[1, 2, 3]").getArray()
|
|
285
|
+
/// let value = array[1] // JavaScriptValue(2)
|
|
286
|
+
/// let outOfRange = array[10] // JavaScriptValue.undefined
|
|
287
|
+
/// ```
|
|
288
|
+
///
|
|
289
|
+
/// ## Setting Values
|
|
290
|
+
///
|
|
291
|
+
/// Automatically expands the array if the index is beyond the current length:
|
|
292
|
+
///
|
|
293
|
+
/// ```swift
|
|
294
|
+
/// let array = try runtime.eval("[1, 2, 3]").getArray()
|
|
295
|
+
/// array[1] = .number(99) // Updates existing element
|
|
296
|
+
/// array[10] = .string("hello") // Expands array to size 11
|
|
297
|
+
/// ```
|
|
298
|
+
///
|
|
299
|
+
/// - Note: This subscript never throws. For strict bounds checking with errors,
|
|
300
|
+
/// use `getValue(at:)` and `set(value:at:)` instead.
|
|
301
|
+
/// - Note: When setting an element beyond the current length, intermediate elements
|
|
302
|
+
/// are filled with `undefined`, matching JavaScript's behavior.
|
|
325
303
|
public subscript(index: Int) -> JavaScriptValue {
|
|
326
304
|
get {
|
|
327
305
|
return (try? self.getValue(at: index)) ?? .undefined
|
|
@@ -337,46 +315,44 @@ public struct JavaScriptArray: JavaScriptType, ~Copyable {
|
|
|
337
315
|
}
|
|
338
316
|
}
|
|
339
317
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
the current length.
|
|
379
|
-
*/
|
|
318
|
+
/// Type-safe subscript for accessing and modifying array elements with automatic conversion.
|
|
319
|
+
///
|
|
320
|
+
/// This subscript provides a convenient way to work with JavaScript array elements using
|
|
321
|
+
/// Swift types that conform to `JavaScriptRepresentable`. It automatically converts between
|
|
322
|
+
/// JavaScript values and Swift types.
|
|
323
|
+
///
|
|
324
|
+
/// - Parameter index: The zero-based index of the element to access or modify
|
|
325
|
+
/// - Returns: An optional value of type `T` if the element exists and can be converted,
|
|
326
|
+
/// or `nil` if the index is out of range or conversion fails
|
|
327
|
+
///
|
|
328
|
+
/// ## Getting Values
|
|
329
|
+
///
|
|
330
|
+
/// When reading, returns `nil` if:
|
|
331
|
+
/// - The index is out of range
|
|
332
|
+
/// - The JavaScript value cannot be converted to type `T`
|
|
333
|
+
///
|
|
334
|
+
/// ```swift
|
|
335
|
+
/// let array = try runtime.eval("[1, 2, 3]").getArray()
|
|
336
|
+
/// let value: Int? = array[0] // Returns 1
|
|
337
|
+
/// let outOfRange: Int? = array[10] // Returns nil
|
|
338
|
+
/// ```
|
|
339
|
+
///
|
|
340
|
+
/// ## Setting Values
|
|
341
|
+
///
|
|
342
|
+
/// When writing:
|
|
343
|
+
/// - Automatically resizes the array if the index is beyond the current length (JavaScript behavior)
|
|
344
|
+
/// - Setting `nil` sets the element to `undefined`
|
|
345
|
+
/// - Accepts any value conforming to `JavaScriptRepresentable`
|
|
346
|
+
///
|
|
347
|
+
/// ```swift
|
|
348
|
+
/// array[0] = 42 // Sets element to number
|
|
349
|
+
/// array[5] = "hello" // Resizes array and sets element
|
|
350
|
+
/// array[1] = nil // Sets element to undefined
|
|
351
|
+
/// ```
|
|
352
|
+
///
|
|
353
|
+
/// - Note: Unlike `getValue(at:)` and `set(value:at:)`, this subscript mimics JavaScript's
|
|
354
|
+
/// dynamic array behavior by automatically expanding the array when setting elements beyond
|
|
355
|
+
/// the current length.
|
|
380
356
|
public subscript<T: JavaScriptRepresentable & ~Copyable>(index: Int) -> T? {
|
|
381
357
|
get {
|
|
382
358
|
return try? T.fromJavaScriptValue(self.getValue(at: index))
|
|
@@ -388,42 +364,41 @@ public struct JavaScriptArray: JavaScriptType, ~Copyable {
|
|
|
388
364
|
if index >= length {
|
|
389
365
|
self.length = index + 1
|
|
390
366
|
}
|
|
391
|
-
let jsiValue =
|
|
392
|
-
newValue
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
367
|
+
let jsiValue =
|
|
368
|
+
if let newValue {
|
|
369
|
+
newValue.toJavaScriptValue(in: runtime).toJSIValue(in: runtime.pointee)
|
|
370
|
+
} else {
|
|
371
|
+
facebook.jsi.Value.undefined()
|
|
372
|
+
}
|
|
396
373
|
expo.setValueAtIndex(runtime.pointee, pointee, index, jsiValue)
|
|
397
374
|
}
|
|
398
375
|
}
|
|
399
376
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
array elements by index, use the numeric subscript `array[0]` instead of `array["0"]`.
|
|
426
|
-
*/
|
|
377
|
+
/// Accesses properties of the array using string keys.
|
|
378
|
+
///
|
|
379
|
+
/// Since JavaScript arrays are also objects, they can have named properties in addition
|
|
380
|
+
/// to numeric indices. This subscript allows you to access and modify these properties.
|
|
381
|
+
///
|
|
382
|
+
/// - Parameter key: The property name to access or modify
|
|
383
|
+
/// - Returns: The value of the property as a `JavaScriptValue`
|
|
384
|
+
///
|
|
385
|
+
/// ## Examples
|
|
386
|
+
///
|
|
387
|
+
/// ```swift
|
|
388
|
+
/// let array = try runtime.eval("[1, 2, 3]").getArray()
|
|
389
|
+
///
|
|
390
|
+
/// // Access built-in properties
|
|
391
|
+
/// let length = array["length"] // JavaScriptValue(3)
|
|
392
|
+
///
|
|
393
|
+
/// // Set custom properties
|
|
394
|
+
/// array["customProperty"] = .string("custom value")
|
|
395
|
+
///
|
|
396
|
+
/// // Access custom properties
|
|
397
|
+
/// let custom = array["customProperty"] // JavaScriptValue("custom value")
|
|
398
|
+
/// ```
|
|
399
|
+
///
|
|
400
|
+
/// - Note: This subscript accesses object properties, not array elements. To access
|
|
401
|
+
/// array elements by index, use the numeric subscript `array[0]` instead of `array["0"]`.
|
|
427
402
|
public subscript(key: String) -> JavaScriptValue {
|
|
428
403
|
get {
|
|
429
404
|
guard let runtime else {
|
|
@@ -441,20 +416,18 @@ public struct JavaScriptArray: JavaScriptType, ~Copyable {
|
|
|
441
416
|
}
|
|
442
417
|
}
|
|
443
418
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
pattern, meaning it only throws if the transform closure throws.
|
|
457
|
-
*/
|
|
419
|
+
/// Transforms each element in the JavaScript array using the provided closure. This method creates a new Swift array
|
|
420
|
+
/// by calling the transform closure on each element of the JavaScript array.
|
|
421
|
+
/// The closure receives a `JavaScriptValue` for each element and returns a transformed value.
|
|
422
|
+
///
|
|
423
|
+
/// - Parameter transform: A closure that accepts a `JavaScriptValue` representing an element
|
|
424
|
+
/// from the array and returns a transformed value. The closure can throw an error, which
|
|
425
|
+
/// will be propagated to the caller.
|
|
426
|
+
/// - Returns: A Swift array containing the transformed elements in the same order as
|
|
427
|
+
/// the original JavaScript array.
|
|
428
|
+
/// - Throws: Any error thrown by the `transform` closure.
|
|
429
|
+
/// - Note: This method uses Swift's standard `map` semantics and follows the `rethrows`
|
|
430
|
+
/// pattern, meaning it only throws if the transform closure throws.
|
|
458
431
|
public func map<T>(_ transform: (_ value: JavaScriptValue) throws -> T) rethrows -> [T] {
|
|
459
432
|
guard let runtime else {
|
|
460
433
|
FatalError.runtimeLost()
|
|
@@ -469,14 +442,12 @@ public struct JavaScriptArray: JavaScriptType, ~Copyable {
|
|
|
469
442
|
return result
|
|
470
443
|
}
|
|
471
444
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
- SeeAlso: `JavaScriptValue.getArray()` for the inverse operation
|
|
479
|
-
*/
|
|
445
|
+
/// Converts the JavaScript array to a `JavaScriptValue`.
|
|
446
|
+
///
|
|
447
|
+
/// - Returns: A `JavaScriptValue` representing this array
|
|
448
|
+
/// - Note: The returned value maintains a reference to the same underlying JavaScript
|
|
449
|
+
/// array, so modifications to the array in JavaScript will be reflected in the value.
|
|
450
|
+
/// - SeeAlso: `JavaScriptValue.getArray()` for the inverse operation
|
|
480
451
|
public func asValue() -> JavaScriptValue {
|
|
481
452
|
guard let runtime else {
|
|
482
453
|
FatalError.runtimeLost()
|
|
@@ -484,43 +455,37 @@ public struct JavaScriptArray: JavaScriptType, ~Copyable {
|
|
|
484
455
|
return JavaScriptValue(runtime, expo.valueFromArray(runtime.pointee, pointee))
|
|
485
456
|
}
|
|
486
457
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
- SeeAlso: `asValue()` for converting to a `JavaScriptValue`
|
|
508
|
-
*/
|
|
458
|
+
/// Converts the array to a `JavaScriptObject`.
|
|
459
|
+
///
|
|
460
|
+
/// Since JavaScript arrays are also objects, this method allows you to access the array
|
|
461
|
+
/// as a generic object to use object-specific APIs like property enumeration or prototype
|
|
462
|
+
/// manipulation.
|
|
463
|
+
///
|
|
464
|
+
/// - Returns: A `JavaScriptObject` representing the same underlying array
|
|
465
|
+
///
|
|
466
|
+
/// ```swift
|
|
467
|
+
/// let array = try runtime.eval("[1, 2, 3]").getArray()
|
|
468
|
+
/// let object = array.toObject()
|
|
469
|
+
///
|
|
470
|
+
/// // Access array properties as an object
|
|
471
|
+
/// let length = object.getProperty("length") // JavaScriptValue(3)
|
|
472
|
+
/// ```
|
|
473
|
+
///
|
|
474
|
+
/// - Note: The returned object maintains a reference to the same underlying JavaScript
|
|
475
|
+
/// array, so modifications through either the array or object interface will affect
|
|
476
|
+
/// the same data.
|
|
477
|
+
/// - SeeAlso: `asValue()` for converting to a `JavaScriptValue`
|
|
509
478
|
public func toObject() -> JavaScriptObject {
|
|
510
479
|
return asValue().getObject()
|
|
511
480
|
}
|
|
512
481
|
|
|
513
|
-
|
|
514
|
-
Errors that can occur when working with JavaScript arrays.
|
|
515
|
-
*/
|
|
482
|
+
/// Errors that can occur when working with JavaScript arrays.
|
|
516
483
|
public enum Errors: Error, Equatable, CustomStringConvertible {
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
- length: The actual length of the array
|
|
523
|
-
*/
|
|
484
|
+
/// The specified index is out of the array's valid range.
|
|
485
|
+
///
|
|
486
|
+
/// - Parameters:
|
|
487
|
+
/// - index: The invalid index that was accessed
|
|
488
|
+
/// - length: The actual length of the array
|
|
524
489
|
case indexOutOfRange(index: Int, length: Int)
|
|
525
490
|
|
|
526
491
|
public var description: String {
|
|
@@ -540,11 +505,9 @@ public struct JavaScriptArray: JavaScriptType, ~Copyable {
|
|
|
540
505
|
// equivalent functionality without requiring protocol conformance.
|
|
541
506
|
|
|
542
507
|
extension JavaScriptArray {
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
- Note: Eagerly evaluates all elements. For large arrays, prefer `forEach(_:)`.
|
|
547
|
-
*/
|
|
508
|
+
/// Returns an array of `(offset, element)` pairs, similar to `Sequence.enumerated()`.
|
|
509
|
+
///
|
|
510
|
+
/// - Note: Eagerly evaluates all elements. For large arrays, prefer `forEach(_:)`.
|
|
548
511
|
public func enumerated() -> [(offset: Int, element: JavaScriptValue)] {
|
|
549
512
|
guard let runtime else {
|
|
550
513
|
FatalError.runtimeLost()
|
|
@@ -558,9 +521,7 @@ extension JavaScriptArray {
|
|
|
558
521
|
return result
|
|
559
522
|
}
|
|
560
523
|
|
|
561
|
-
|
|
562
|
-
Calls the given closure on each element in the array.
|
|
563
|
-
*/
|
|
524
|
+
/// Calls the given closure on each element in the array.
|
|
564
525
|
public func forEach(_ body: (JavaScriptValue) throws -> Void) rethrows {
|
|
565
526
|
guard let runtime else {
|
|
566
527
|
FatalError.runtimeLost()
|
|
@@ -571,9 +532,7 @@ extension JavaScriptArray {
|
|
|
571
532
|
}
|
|
572
533
|
}
|
|
573
534
|
|
|
574
|
-
|
|
575
|
-
Returns an array of elements satisfying the given predicate.
|
|
576
|
-
*/
|
|
535
|
+
/// Returns an array of elements satisfying the given predicate.
|
|
577
536
|
public func filter(_ isIncluded: (JavaScriptValue) throws -> Bool) rethrows -> [JavaScriptValue] {
|
|
578
537
|
guard let runtime else {
|
|
579
538
|
FatalError.runtimeLost()
|
|
@@ -589,10 +548,10 @@ extension JavaScriptArray {
|
|
|
589
548
|
return result
|
|
590
549
|
}
|
|
591
550
|
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
551
|
+
/// Returns the result of combining the elements using the given closure.
|
|
552
|
+
public func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, JavaScriptValue) throws -> Result)
|
|
553
|
+
rethrows -> Result
|
|
554
|
+
{
|
|
596
555
|
guard let runtime else {
|
|
597
556
|
FatalError.runtimeLost()
|
|
598
557
|
}
|