react-native-nitro-modules 0.22.1 → 0.24.0

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 (60) hide show
  1. package/NitroModules.podspec +1 -0
  2. package/README.md +6 -0
  3. package/android/build.gradle +1 -1
  4. package/android/gradle.properties +1 -1
  5. package/android/src/main/cpp/registry/DefaultConstructableObject.hpp +1 -1
  6. package/android/src/main/java/com/margelo/nitro/views/HybridView.kt +11 -0
  7. package/cpp/core/ArrayBuffer.cpp +3 -5
  8. package/cpp/core/ArrayBuffer.hpp +2 -2
  9. package/cpp/core/HybridFunction.hpp +5 -1
  10. package/cpp/core/HybridObject.cpp +3 -1
  11. package/cpp/core/Promise.hpp +11 -8
  12. package/cpp/jsi/JSICache.hpp +3 -3
  13. package/cpp/jsi/JSIConverter+ArrayBuffer.hpp +1 -1
  14. package/cpp/jsi/JSIConverter+Exception.hpp +4 -1
  15. package/cpp/jsi/JSIConverter+Function.hpp +24 -67
  16. package/cpp/jsi/JSIConverter+Promise.hpp +3 -2
  17. package/cpp/prototype/HybridObjectPrototype.cpp +12 -9
  18. package/cpp/registry/HybridObjectRegistry.cpp +3 -0
  19. package/cpp/templates/PromiseType.hpp +12 -0
  20. package/cpp/threading/Dispatcher.cpp +7 -5
  21. package/cpp/utils/BorrowingReference.hpp +40 -43
  22. package/cpp/utils/JSCallback.hpp +132 -0
  23. package/cpp/utils/NitroDefines.hpp +1 -8
  24. package/cpp/utils/NitroTypeInfo.cpp +80 -0
  25. package/cpp/utils/NitroTypeInfo.hpp +8 -65
  26. package/cpp/utils/WeakReference.hpp +6 -7
  27. package/cpp/views/CachedProp.hpp +2 -1
  28. package/ios/turbomodule/NativeNitroModules+NewArch.mm +1 -1
  29. package/ios/utils/RuntimeError.hpp +1 -1
  30. package/lib/commonjs/Sync.js +2 -0
  31. package/lib/commonjs/Sync.js.map +1 -0
  32. package/lib/commonjs/index.js +22 -0
  33. package/lib/commonjs/index.js.map +1 -1
  34. package/lib/commonjs/views/HybridView.js +0 -11
  35. package/lib/commonjs/views/HybridView.js.map +1 -1
  36. package/lib/commonjs/views/getHostComponent.js +20 -1
  37. package/lib/commonjs/views/getHostComponent.js.map +1 -1
  38. package/lib/module/Sync.js +2 -0
  39. package/lib/module/Sync.js.map +1 -0
  40. package/lib/module/index.js +2 -0
  41. package/lib/module/index.js.map +1 -1
  42. package/lib/module/views/HybridView.js +0 -26
  43. package/lib/module/views/HybridView.js.map +1 -1
  44. package/lib/module/views/getHostComponent.js +21 -1
  45. package/lib/module/views/getHostComponent.js.map +1 -1
  46. package/lib/tsconfig.build.tsbuildinfo +1 -1
  47. package/lib/typescript/Sync.d.ts +11 -0
  48. package/lib/typescript/Sync.d.ts.map +1 -0
  49. package/lib/typescript/index.d.ts +2 -0
  50. package/lib/typescript/index.d.ts.map +1 -1
  51. package/lib/typescript/views/HybridView.d.ts +89 -16
  52. package/lib/typescript/views/HybridView.d.ts.map +1 -1
  53. package/lib/typescript/views/getHostComponent.d.ts +46 -3
  54. package/lib/typescript/views/getHostComponent.d.ts.map +1 -1
  55. package/package.json +4 -4
  56. package/src/Sync.ts +8 -0
  57. package/src/index.ts +3 -0
  58. package/src/views/HybridView.ts +96 -18
  59. package/src/views/getHostComponent.ts +67 -5
  60. package/cpp/utils/OwningLock.hpp +0 -56
@@ -9,29 +9,107 @@ export interface ViewPlatformSpec {
9
9
  }
10
10
 
11
11
  /**
12
- * Represents a Nitro `HybridView` which is implemented in a native language
13
- * like Swift or Kotlin.
12
+ * Represents props for a Hybrid View.
13
+ * Such props are implemented on the native side, and can be
14
+ * set from JS using React props.
15
+ * @example
16
+ * ```ts
17
+ * // Definition:
18
+ * type Direction = 'horizontal' | 'vertical'
19
+ * interface ScrollViewProps extends HybridViewProps {
20
+ * direction: Direction
21
+ * }
22
+ * export type ScrollView = HybridView<ScrollViewProps>
14
23
  *
15
- * `HybridViews`s use the Nitro Tunnel for efficient, low-overhead JS <-> Native communication.
24
+ * // in React:
25
+ * function App() {
26
+ * return <HybridScrollView direction="vertical" />
27
+ * }
28
+ * ```
29
+ */
30
+ export interface HybridViewProps {
31
+ /* no default props */
32
+ }
33
+
34
+ /**
35
+ * Represents methods for a Hybrid View.
36
+ * Such methods are implemented on the native side, and can be
37
+ * called from JS using the `hybridRef`.
38
+ * @example
39
+ * ```ts
40
+ * // Definition:
41
+ * interface ScrollViewProps extends HybridViewProps { … }
42
+ * interface ScrollViewMethods extends HybridViewMethods {
43
+ * scrollTo(y: number): void
44
+ * }
45
+ * export type ScrollView = HybridView<ScrollViewProps, ScrollViewMethods>
16
46
  *
17
- * All `HybridViews`s have a C++ Fabric View base with a backing Shadow Node.
47
+ * // in React:
48
+ * function App() {
49
+ * const ref = useRef<ScrollView>(null)
50
+ * useLayoutEffect(() => {
51
+ * ref.current.scrollTo(400)
52
+ * }, [])
53
+ * return <HybridScrollView hybridRef={ref} />
54
+ * }
55
+ * ```
56
+ */
57
+ export interface HybridViewMethods {}
58
+
59
+ /**
60
+ * The type of a {@linkcode DefaultHybridViewProps.hybridRef hybridRef}.
61
+ * @example
62
+ * ```ts
63
+ * // declaration:
64
+ * interface ScrollViewProps extends HybridViewProps { … }
65
+ * interface ScrollViewMethods extends HybridViewMethods {
66
+ * scrollTo(y: number): void
67
+ * }
68
+ * export type ScrollView = HybridView<ScrollViewProps, ScrollViewMethods>
69
+ * export type ScrollViewRef = HybridRef<ScrollViewProps, ScrollViewMethods>
18
70
  *
19
- * - TypeScript Properties (`name: Type`) will be React Props
20
- * - TypeScript Methods (`name(): Type`) will be Ref Methods
71
+ * // in react:
72
+ * function App() {
73
+ * const ref = useRef<ScrollViewRef>(null)
74
+ * useLayoutEffect(() => {
75
+ * ref.current.scrollTo(400)
76
+ * }, [])
77
+ * return <ScrollView hybridRef={ref} />
78
+ * }
79
+ * ```
80
+ */
81
+ export type HybridRef<
82
+ Props extends HybridViewProps,
83
+ Methods extends HybridViewMethods = {},
84
+ > = HybridObject & Props & Methods
85
+
86
+ /**
87
+ * This interface acts as a tag for Hybrid Views so nitrogen detects them.
88
+ */
89
+ interface HybridViewTag extends HybridObject {}
90
+
91
+ /**
92
+ * Represents a Nitro Hybrid View.
93
+ *
94
+ * The Hybrid View's implementation is in native iOS or Android, and is backed
95
+ * by a {@linkcode HybridObject}.
96
+ *
97
+ * Each view has {@linkcode HybridViewProps}, and can optionally also
98
+ * have custom {@linkcode HybridViewMethods}.
99
+ *
100
+ * Properties can be set using React props, and methods can be called after obtaining
101
+ * a reference to the {@linkcode HybridObject} via {@linkcode DefaultHybridViewProps.hybridRef hybridRef}.
21
102
  *
103
+ * The view can be rendered in React (Native).
22
104
  * @example
23
- * ```tsx
24
- * export interface Camera extends HybridView {
25
- * zoom: number
26
- * flash: boolean
27
- * takePhoto(): Image
28
- * }
105
+ * ```ts
106
+ * interface ScrollViewProps extends HybridViewProps { … }
107
+ * interface ScrollViewMethods extends HybridViewMethods { … }
108
+ * export type ScrollView = HybridView<ScrollViewProps, ScrollViewMethods>
29
109
  * ```
30
110
  */
31
- export interface HybridView<
111
+ export type HybridView<
112
+ Props extends HybridViewProps,
113
+ Methods extends HybridViewMethods = {},
32
114
  Platforms extends ViewPlatformSpec = { ios: 'swift'; android: 'kotlin' },
33
- > extends HybridObject<Platforms> {
34
- /* empty interface for now */
35
- }
36
-
37
- export * from './getHostComponent'
115
+ > = HybridViewTag & HybridObject<Platforms> & Props & Methods
@@ -1,6 +1,11 @@
1
- import { Platform, type HostComponent } from 'react-native'
1
+ import { Platform, type HostComponent, type ViewProps } from 'react-native'
2
2
  // @ts-expect-error this unfortunately isn't typed or default-exported.
3
3
  import * as NativeComponentRegistry from 'react-native/Libraries/NativeComponent/NativeComponentRegistry'
4
+ import type {
5
+ HybridView,
6
+ HybridViewMethods,
7
+ HybridViewProps,
8
+ } from './HybridView'
4
9
 
5
10
  export interface ViewConfig<Props> {
6
11
  uiViewClassName: string
@@ -11,16 +16,73 @@ export interface ViewConfig<Props> {
11
16
  }
12
17
 
13
18
  /**
14
- * Finds and returns a native view (aka {@linkcode HostComponent}) via the given {@linkcode name}.
19
+ * Represents all default props a Nitro HybridView has.
15
20
  */
16
- export function getHostComponent<Props>(
21
+ interface DefaultHybridViewProps<RefType> extends ViewProps {
22
+ /**
23
+ * A `ref` to the {@linkcode HybridObject} this Hybrid View is rendering.
24
+ *
25
+ * The `hybridRef` property expects a stable Ref object received from `useRef` or `createRef`.
26
+ * @example
27
+ * ```jsx
28
+ * function App() {
29
+ * return (
30
+ * <HybridScrollView
31
+ * hybridRef={{ f: (ref) => {
32
+ * ref.current.scrollTo(400)
33
+ * }
34
+ * />
35
+ * )
36
+ * }
37
+ * ```
38
+ */
39
+ hybridRef?: (ref: RefType) => void
40
+ }
41
+
42
+ // Due to a React limitation, functions cannot be passed to native directly
43
+ // because RN converts them to booleans (`true`). Nitro knows this and just
44
+ // wraps functions as objects - the original function is stored in `f`.
45
+ type WrapFunctionsInObjects<Props> = {
46
+ [K in keyof Props]: Props[K] extends Function
47
+ ? { f: Props[K] }
48
+ : Props[K] extends Function | undefined
49
+ ? { f: Props[K] }
50
+ : Props[K]
51
+ }
52
+
53
+ /**
54
+ * Represents a React Native view, implemented as a Nitro View, with the given props and methods.
55
+ *
56
+ * @note Every React Native view has a {@linkcode DefaultHybridViewProps.hybridRef hybridRef} which can be used to gain access
57
+ * to the underlying Nitro {@linkcode HybridView}.
58
+ * @note Every function/callback is wrapped as a `{ f: … }` object.
59
+ * @note Every method can be called on the Ref. Including setting properties directly.
60
+ */
61
+ export type ReactNativeView<
62
+ Props extends HybridViewProps,
63
+ Methods extends HybridViewMethods,
64
+ > = HostComponent<
65
+ WrapFunctionsInObjects<
66
+ DefaultHybridViewProps<HybridView<Props, Methods>> & Props
67
+ >
68
+ >
69
+
70
+ /**
71
+ * Finds and returns a native view (aka "HostComponent") via the given {@linkcode name}.
72
+ *
73
+ * The view is bridged to a native Hybrid Object using Nitro Views.
74
+ */
75
+ export function getHostComponent<
76
+ Props extends HybridViewProps,
77
+ Methods extends HybridViewMethods,
78
+ >(
17
79
  name: string,
18
80
  getViewConfig: () => ViewConfig<Props>
19
- ): HostComponent<Props> {
81
+ ): ReactNativeView<Props, Methods> {
20
82
  if (NativeComponentRegistry == null) {
21
83
  throw new Error(
22
84
  `NativeComponentRegistry is not available on ${Platform.OS}!`
23
85
  )
24
86
  }
25
- return NativeComponentRegistry.get<Props>(name, getViewConfig)
87
+ return NativeComponentRegistry.get(name, getViewConfig)
26
88
  }
@@ -1,56 +0,0 @@
1
- //
2
- // OwningLock.hpp
3
- // Nitro
4
- //
5
- // Created by Marc Rousavy on 30.07.24.
6
- //
7
-
8
- #pragma once
9
-
10
- namespace margelo::nitro {
11
- template <typename T>
12
- class BorrowingReference;
13
- }
14
-
15
- #include "BorrowingReference.hpp"
16
- #include <cstddef>
17
- #include <mutex>
18
-
19
- namespace margelo::nitro {
20
-
21
- /**
22
- * An `OwningLock<T>` is a RAII instance that locks the given caller thread guaranteed safe access
23
- * to a `BorrowingReference<T>`.
24
- * The `BorrowingReference<T>` cannot be deleted while an `OwningLock<T>` of it is alive.
25
- *
26
- * This is useful in JSI, because Hermes runs garbage collection on a separate Thread,
27
- * and the separate Thread can delete an `BorrowingReference<T>` while it's still in use.
28
- * The `OwningLock<T>` prevents exactly this problem by blocking the GC destructor until
29
- * the `OwningLock<T>` is released.
30
- *
31
- * To create an `OwningLock<T>`, simply call `lock()` on an `BorrowingReference<T>`.
32
- */
33
- template <typename T>
34
- class OwningLock final {
35
- private:
36
- explicit OwningLock(const BorrowingReference<T>& reference) : _reference(reference) {
37
- _reference._state->mutex.lock();
38
- }
39
-
40
- public:
41
- ~OwningLock() {
42
- _reference._state->mutex.unlock();
43
- }
44
-
45
- OwningLock() = delete;
46
- OwningLock(const OwningLock&) = delete;
47
- OwningLock(OwningLock&&) = delete;
48
-
49
- private:
50
- BorrowingReference<T> _reference;
51
-
52
- private:
53
- friend class BorrowingReference<T>;
54
- };
55
-
56
- } // namespace margelo::nitro