expo-modules-jsi 58.0.4 → 58.0.6

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 (34) hide show
  1. package/CHANGELOG.md +9 -5
  2. package/apple/Benchmarks/HostObjectBenchmarks.swift +57 -0
  3. package/apple/Sources/ExpoModulesJSI/Coding/JavaScriptCodable+Primitives.swift +4 -6
  4. package/apple/Sources/ExpoModulesJSI/Protocols/JSIRepresentable.swift +2 -2
  5. package/apple/Sources/ExpoModulesJSI/Protocols/JavaScriptRepresentable.swift +2 -3
  6. package/apple/Sources/ExpoModulesJSI/Runtime/JavaScriptRuntime.swift +24 -17
  7. package/apple/Sources/ExpoModulesJSI/Runtime/JavaScriptRuntimeHandle.swift +67 -0
  8. package/apple/Sources/ExpoModulesJSI/Runtime/JavaScriptValuesBuffer.swift +3 -2
  9. package/apple/Sources/ExpoModulesJSI/Runtime/Values/JavaScriptArray.swift +53 -35
  10. package/apple/Sources/ExpoModulesJSI/Runtime/Values/JavaScriptFunction.swift +2 -2
  11. package/apple/Sources/ExpoModulesJSI/Runtime/Values/JavaScriptObject.swift +79 -59
  12. package/apple/Sources/ExpoModulesJSI/Runtime/Values/JavaScriptValue.swift +63 -46
  13. package/apple/Sources/ExpoModulesJSI/Utilities/String+JSI.swift +10 -0
  14. package/apple/Sources/ExpoModulesJSI-Cxx/include/HostObject.h +2 -2
  15. package/apple/Sources/ExpoModulesJSI-Cxx/include/HostObjectCallbacks.h +17 -8
  16. package/apple/Sources/ExpoModulesJSI-Cxx/include/JSIUtils.h +20 -0
  17. package/apple/Tests/JavaScriptRuntimeTests.swift +40 -0
  18. package/apple/Tests/JavaScriptValueTests.swift +18 -0
  19. package/apple/Tests/JavaScriptValuesBufferTests.swift +14 -0
  20. package/package.json +1 -2
  21. package/apple/.generated/module.modulemap +0 -6
  22. package/apple/Products/ExpoModulesJSI.xcframework/Info.plist +0 -107
  23. package/apple/Products/ExpoModulesJSI.xcframework/ios-arm64/.build-hash +0 -0
  24. package/apple/Products/ExpoModulesJSI.xcframework/ios-arm64/ExpoModulesJSI.framework/ExpoModulesJSI +0 -0
  25. package/apple/Products/ExpoModulesJSI.xcframework/ios-arm64_x86_64-maccatalyst/.build-hash +0 -0
  26. package/apple/Products/ExpoModulesJSI.xcframework/ios-arm64_x86_64-maccatalyst/ExpoModulesJSI.framework/ExpoModulesJSI +0 -0
  27. package/apple/Products/ExpoModulesJSI.xcframework/ios-arm64_x86_64-simulator/.build-hash +0 -0
  28. package/apple/Products/ExpoModulesJSI.xcframework/ios-arm64_x86_64-simulator/ExpoModulesJSI.framework/ExpoModulesJSI +0 -0
  29. package/apple/Products/ExpoModulesJSI.xcframework/macos-arm64_x86_64/.build-hash +0 -0
  30. package/apple/Products/ExpoModulesJSI.xcframework/macos-arm64_x86_64/ExpoModulesJSI.framework/ExpoModulesJSI +0 -0
  31. package/apple/Products/ExpoModulesJSI.xcframework/tvos-arm64/.build-hash +0 -0
  32. package/apple/Products/ExpoModulesJSI.xcframework/tvos-arm64/ExpoModulesJSI.framework/ExpoModulesJSI +0 -0
  33. package/apple/Products/ExpoModulesJSI.xcframework/tvos-arm64_x86_64-simulator/.build-hash +0 -0
  34. package/apple/Products/ExpoModulesJSI.xcframework/tvos-arm64_x86_64-simulator/ExpoModulesJSI.framework/ExpoModulesJSI +0 -0
@@ -4,6 +4,7 @@
4
4
 
5
5
  #include <swift/bridging>
6
6
  #include <jsi/jsi.h>
7
+ #include <string>
7
8
 
8
9
  #include "RetainedSwiftPointer.h"
9
10
 
@@ -20,16 +21,24 @@ public:
20
21
  // Swift side can fill the caller's slot from inside its guaranteed-reference scope.
21
22
  // Both return whether the Swift side stored an error in `CppError`'s thread-local slot, so the
22
23
  // caller reads that slot only when needed.
23
- using Getter = bool(Context, const char *_Nonnull name, facebook::jsi::Value *_Nonnull result);
24
- using Setter = bool(Context, const char *_Nonnull name, void *_Nonnull value);
24
+ using Getter = bool(Context, const facebook::jsi::PropNameID *_Nonnull name, facebook::jsi::Value *_Nonnull result);
25
+ using Setter = bool(Context, const facebook::jsi::PropNameID *_Nonnull name, void *_Nonnull value);
25
26
  using PropertyNamesGetter = PropNameIds(Context);
26
27
  using Deallocator = void(Context);
27
28
 
28
- explicit HostObjectCallbacks(Context context, Getter getter, Setter *_Nullable setter, PropertyNamesGetter propertyNamesGetter, Deallocator deallocator)
29
+ explicit HostObjectCallbacks(Context context, Getter getter, Setter setter, PropertyNamesGetter propertyNamesGetter, Deallocator deallocator)
29
30
  : _context(context), _getter(getter), _setter(setter), _propertyNamesGetter(propertyNamesGetter), _deallocator(deallocator) {}
30
31
 
31
- inline bool get(const char *_Nonnull name, facebook::jsi::Value &result) const {
32
- return _getter(_context, name, &result);
32
+ /**
33
+ Creates callbacks for a read-only host object: assignment from JavaScript throws a `jsi::JSError`
34
+ without calling into Swift. A separate constructor rather than a nullable setter, because Swift can't
35
+ pass a function reference where an optional C function pointer is expected.
36
+ */
37
+ explicit HostObjectCallbacks(Context context, Getter getter, PropertyNamesGetter propertyNamesGetter, Deallocator deallocator)
38
+ : _context(context), _getter(getter), _setter(nullptr), _propertyNamesGetter(propertyNamesGetter), _deallocator(deallocator) {}
39
+
40
+ inline bool get(const facebook::jsi::PropNameID &name, facebook::jsi::Value &result) const {
41
+ return _getter(_context, &name, &result);
33
42
  }
34
43
 
35
44
  /**
@@ -41,16 +50,16 @@ public:
41
50
  JSI call frame above this on the stack; calling outside that context will surface
42
51
  the throw as an unhandled C++ exception.
43
52
  */
44
- inline bool set(facebook::jsi::Runtime &runtime, const char *_Nonnull name, const facebook::jsi::Value &value) const {
53
+ inline bool set(facebook::jsi::Runtime &runtime, const facebook::jsi::PropNameID &name, const facebook::jsi::Value &value) const {
45
54
  if (_setter == nullptr) {
46
55
  throw facebook::jsi::JSError(
47
56
  runtime,
48
- std::string("Cannot set property '") + name + "' on a read-only host object: "
57
+ std::string("Cannot set property '") + name.utf8(runtime) + "' on a read-only host object: "
49
58
  "no setter was provided when the host object was created. "
50
59
  "Pass a `set` closure to `createHostObject` to make this property writable."
51
60
  );
52
61
  }
53
- return _setter(_context, name, (void *)(&value));
62
+ return _setter(_context, &name, (void *)(&value));
54
63
  }
55
64
 
56
65
  inline PropNameIds getPropertyNames() const {
@@ -228,6 +228,26 @@ inline void getStringData(
228
228
  #endif
229
229
  }
230
230
 
231
+ /**
232
+ Same as `getStringData`, but for a `jsi::PropNameID`.
233
+ */
234
+ inline void getPropNameIdData(
235
+ jsi::IRuntime &runtime,
236
+ const jsi::PropNameID &propNameId,
237
+ void *ctx,
238
+ void (*callback)(void *_Nullable ctx, bool ascii, const void *_Nullable data, size_t num)
239
+ ) {
240
+ #if defined(REACT_NATIVE_VERSION_MAJOR) && defined(REACT_NATIVE_VERSION_MINOR) && \
241
+ (REACT_NATIVE_VERSION_MAJOR > 0 || REACT_NATIVE_VERSION_MINOR >= 86)
242
+ runtime.getPropNameIdData(propNameId, ctx, callback);
243
+ #else
244
+ auto forward = [ctx, callback](bool ascii, const void *data, size_t num) {
245
+ callback(ctx, ascii, data, num);
246
+ };
247
+ propNameId.getPropNameIdData(runtime, forward);
248
+ #endif
249
+ }
250
+
231
251
  // MARK: - ArrayBuffer
232
252
 
233
253
  /**
@@ -280,6 +280,46 @@ struct JavaScriptRuntimeTests {
280
280
  #expect(result.getString() == "hello")
281
281
  }
282
282
 
283
+ @Test
284
+ func `host object receives non-ASCII property names`() throws {
285
+ var receivedNames: [String] = []
286
+ var setNames: [String] = []
287
+
288
+ let hostObject = runtime.createHostObject(
289
+ get: { name in
290
+ receivedNames.append(name)
291
+ return .undefined
292
+ },
293
+ set: { name, _ in
294
+ setNames.append(name)
295
+ }
296
+ )
297
+
298
+ runtime.global().setProperty("hostObj", value: hostObject.asValue())
299
+ _ = try runtime.eval("globalThis.hostObj['właściwość']; globalThis.hostObj['🚀'] = 1")
300
+
301
+ #expect(receivedNames == ["właściwość"])
302
+ #expect(setNames == ["🚀"])
303
+ }
304
+
305
+ @Test
306
+ func `host object receives long property names`() throws {
307
+ var receivedName: String?
308
+ let longName = String(repeating: "a", count: 300)
309
+
310
+ let hostObject = runtime.createHostObject(
311
+ get: { name in
312
+ receivedName = name
313
+ return .undefined
314
+ }
315
+ )
316
+
317
+ runtime.global().setProperty("hostObj", value: hostObject.asValue())
318
+ _ = try runtime.eval("globalThis.hostObj['\(longName)']")
319
+
320
+ #expect(receivedName == longName)
321
+ }
322
+
283
323
  @Test
284
324
  func `isHostObject distinguishes host objects from plain ones`() {
285
325
  let hostObject = runtime.createHostObject(
@@ -726,3 +726,21 @@ struct JavaScriptValueTests {
726
726
  #expect(pointee1 == pointee2)
727
727
  }
728
728
  }
729
+
730
+ @Suite
731
+ @JavaScriptActor
732
+ struct JavaScriptValueRuntimeLifetimeTests {
733
+ @Test
734
+ func `runtime-free value kinds keep working after the runtime is gone`() throws {
735
+ var runtime: JavaScriptRuntime? = JavaScriptRuntime()
736
+ let bool = JavaScriptValue(runtime!, true)
737
+
738
+ // Values don't keep the runtime alive, so this deallocates it.
739
+ runtime = nil
740
+
741
+ // A boolean doesn't need the runtime, so these take the runtime-free paths instead of trapping.
742
+ #expect(try bool.jsonStringify() == "true")
743
+ #expect(bool.copy().getBool() == true)
744
+ #expect(bool.isEqual(to: .true()))
745
+ }
746
+ }
@@ -15,6 +15,20 @@ struct JavaScriptValuesBufferTests {
15
15
  #expect(try buffer[2].asBool() == true)
16
16
  }
17
17
 
18
+ @Test
19
+ func `copying accepts runtime-free values`() throws {
20
+ let buffer = JavaScriptValuesBuffer.copying(
21
+ in: runtime,
22
+ values: [.undefined, .null, .number(1), .true(), JavaScriptValue(runtime, "four")]
23
+ )
24
+ #expect(buffer.count == 5)
25
+ #expect(buffer[0].isUndefined())
26
+ #expect(buffer[1].isNull())
27
+ #expect(try buffer[2].asInt() == 1)
28
+ #expect(try buffer[3].asBool() == true)
29
+ #expect(try buffer[4].asString() == "four")
30
+ }
31
+
18
32
  @Test
19
33
  func `empty buffer has zero count and deinits cleanly`() {
20
34
  let buffer = JavaScriptValuesBuffer.allocate(in: runtime, capacity: 0)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-modules-jsi",
3
- "version": "58.0.4",
3
+ "version": "58.0.6",
4
4
  "description": "The JavaScript Interface for Expo Modules",
5
5
  "main": "index.js",
6
6
  "sideEffects": [],
@@ -41,7 +41,6 @@
41
41
  "./apple/scripts/test.sh"
42
42
  ]
43
43
  },
44
- "gitHead": "ad41d067bd3df6dd12f1788acc6b54a68e7a650d",
45
44
  "scripts": {
46
45
  "benchmark": "TEST_RUNNER_EXPO_BENCHMARK=1 DESTINATION=\"${DESTINATION:-platform=macOS,variant=Mac Catalyst}\" apple/scripts/test.sh -configuration Release -only-testing Benchmarks -enableCodeCoverage NO",
47
46
  "build:xcframework": "apple/scripts/build-xcframework.sh",
@@ -1,6 +0,0 @@
1
- module jsi {
2
- header "/Users/alanhughes/Work/expo/packages/expo-modules-jsi/.expo-prebuild/pods-stage/Headers/Public/React-jsi/jsi/jsi.h"
3
- header "/Users/alanhughes/Work/expo/packages/expo-modules-jsi/.expo-prebuild/pods-stage/Headers/Public/React-jsi/jsi/instrumentation.h"
4
-
5
- export *
6
- }
@@ -1,107 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
- <plist version="1.0">
4
- <dict>
5
- <key>AvailableLibraries</key>
6
- <array>
7
- <dict>
8
- <key>BinaryPath</key>
9
- <string>ExpoModulesJSI.framework/ExpoModulesJSI</string>
10
- <key>LibraryIdentifier</key>
11
- <string>ios-arm64</string>
12
- <key>LibraryPath</key>
13
- <string>ExpoModulesJSI.framework</string>
14
- <key>SupportedArchitectures</key>
15
- <array>
16
- <string>arm64</string>
17
- </array>
18
- <key>SupportedPlatform</key>
19
- <string>ios</string>
20
- </dict>
21
- <dict>
22
- <key>BinaryPath</key>
23
- <string>ExpoModulesJSI.framework/ExpoModulesJSI</string>
24
- <key>LibraryIdentifier</key>
25
- <string>ios-arm64_x86_64-maccatalyst</string>
26
- <key>LibraryPath</key>
27
- <string>ExpoModulesJSI.framework</string>
28
- <key>SupportedArchitectures</key>
29
- <array>
30
- <string>arm64</string>
31
- <string>x86_64</string>
32
- </array>
33
- <key>SupportedPlatform</key>
34
- <string>ios</string>
35
- <key>SupportedPlatformVariant</key>
36
- <string>maccatalyst</string>
37
- </dict>
38
- <dict>
39
- <key>BinaryPath</key>
40
- <string>ExpoModulesJSI.framework/ExpoModulesJSI</string>
41
- <key>LibraryIdentifier</key>
42
- <string>ios-arm64_x86_64-simulator</string>
43
- <key>LibraryPath</key>
44
- <string>ExpoModulesJSI.framework</string>
45
- <key>SupportedArchitectures</key>
46
- <array>
47
- <string>arm64</string>
48
- <string>x86_64</string>
49
- </array>
50
- <key>SupportedPlatform</key>
51
- <string>ios</string>
52
- <key>SupportedPlatformVariant</key>
53
- <string>simulator</string>
54
- </dict>
55
- <dict>
56
- <key>BinaryPath</key>
57
- <string>ExpoModulesJSI.framework/ExpoModulesJSI</string>
58
- <key>LibraryIdentifier</key>
59
- <string>macos-arm64_x86_64</string>
60
- <key>LibraryPath</key>
61
- <string>ExpoModulesJSI.framework</string>
62
- <key>SupportedArchitectures</key>
63
- <array>
64
- <string>arm64</string>
65
- <string>x86_64</string>
66
- </array>
67
- <key>SupportedPlatform</key>
68
- <string>macos</string>
69
- </dict>
70
- <dict>
71
- <key>BinaryPath</key>
72
- <string>ExpoModulesJSI.framework/ExpoModulesJSI</string>
73
- <key>LibraryIdentifier</key>
74
- <string>tvos-arm64</string>
75
- <key>LibraryPath</key>
76
- <string>ExpoModulesJSI.framework</string>
77
- <key>SupportedArchitectures</key>
78
- <array>
79
- <string>arm64</string>
80
- </array>
81
- <key>SupportedPlatform</key>
82
- <string>tvos</string>
83
- </dict>
84
- <dict>
85
- <key>BinaryPath</key>
86
- <string>ExpoModulesJSI.framework/ExpoModulesJSI</string>
87
- <key>LibraryIdentifier</key>
88
- <string>tvos-arm64_x86_64-simulator</string>
89
- <key>LibraryPath</key>
90
- <string>ExpoModulesJSI.framework</string>
91
- <key>SupportedArchitectures</key>
92
- <array>
93
- <string>arm64</string>
94
- <string>x86_64</string>
95
- </array>
96
- <key>SupportedPlatform</key>
97
- <string>tvos</string>
98
- <key>SupportedPlatformVariant</key>
99
- <string>simulator</string>
100
- </dict>
101
- </array>
102
- <key>CFBundlePackageType</key>
103
- <string>XFWK</string>
104
- <key>XCFrameworkFormatVersion</key>
105
- <string>1.0</string>
106
- </dict>
107
- </plist>