react-native-nitro-modules 0.10.0 → 0.11.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.
- package/NitroModules.podspec +2 -0
- package/README.md +1 -1
- package/android/CMakeLists.txt +3 -0
- package/android/build.gradle +26 -2
- package/android/src/main/cpp/JNIOnLoad.cpp +5 -5
- package/android/src/main/cpp/turbomodule/JNitroModules.cpp +39 -0
- package/android/src/main/cpp/turbomodule/JNitroModules.hpp +37 -0
- package/android/src/main/java/com/margelo/nitro/NitroModules.kt +69 -0
- package/android/src/main/java/com/margelo/nitro/NitroModulesPackage.kt +34 -0
- package/android/src/main/java/com/margelo/nitro/core/HybridObject.kt +6 -2
- package/android/src/newarch/NitroModulesSpec.kt +6 -0
- package/android/src/oldarch/NitroModulesSpec.kt +9 -0
- package/cpp/core/HybridFunction.hpp +12 -3
- package/cpp/entrypoint/HybridNitroModulesProxy.cpp +55 -0
- package/cpp/entrypoint/HybridNitroModulesProxy.hpp +48 -0
- package/cpp/entrypoint/InstallNitro.cpp +28 -0
- package/cpp/entrypoint/InstallNitro.hpp +41 -0
- package/cpp/jsi/JSIConverter+HostObject.hpp +73 -0
- package/cpp/jsi/JSIConverter+HybridObject.hpp +1 -1
- package/cpp/jsi/JSIConverter.hpp +1 -0
- package/ios/core/HybridObjectSpec.swift +1 -1
- package/ios/platform/NitroLogger.mm +0 -1
- package/ios/turbomodule/NativeNitroModules+NewArch.mm +67 -0
- package/ios/turbomodule/NativeNitroModules+OldArch.mm +68 -0
- package/ios/turbomodule/NativeNitroModules.h +22 -0
- package/lib/BoxedHybridObject.d.ts +12 -0
- package/lib/BoxedHybridObject.js +1 -0
- package/lib/ModuleNotFoundError.js +3 -13
- package/lib/NitroModules.d.ts +1 -83
- package/lib/NitroModules.js +2 -94
- package/lib/NitroModulesProxy.d.ts +58 -0
- package/lib/NitroModulesProxy.js +1 -0
- package/lib/commonjs/BoxedHybridObject.js +6 -0
- package/lib/commonjs/BoxedHybridObject.js.map +1 -0
- package/lib/commonjs/ModuleNotFoundError.js +3 -15
- package/lib/commonjs/ModuleNotFoundError.js.map +1 -1
- package/lib/commonjs/NitroModules.js +11 -100
- package/lib/commonjs/NitroModules.js.map +1 -1
- package/lib/commonjs/NitroModulesProxy.js +6 -0
- package/lib/commonjs/NitroModulesProxy.js.map +1 -0
- package/lib/commonjs/turbomodule/NativeNitroModules.js +36 -0
- package/lib/commonjs/turbomodule/NativeNitroModules.js.map +1 -0
- package/lib/commonjs/turbomodule/NativeNitroModules.web.js +17 -0
- package/lib/commonjs/turbomodule/NativeNitroModules.web.js.map +1 -0
- package/lib/module/BoxedHybridObject.js +4 -0
- package/lib/module/BoxedHybridObject.js.map +1 -0
- package/lib/module/ModuleNotFoundError.js +3 -15
- package/lib/module/ModuleNotFoundError.js.map +1 -1
- package/lib/module/NitroModules.js +2 -100
- package/lib/module/NitroModules.js.map +1 -1
- package/lib/module/NitroModulesProxy.js +4 -0
- package/lib/module/NitroModulesProxy.js.map +1 -0
- package/lib/module/turbomodule/NativeNitroModules.js +31 -0
- package/lib/module/turbomodule/NativeNitroModules.js.map +1 -0
- package/lib/{NitroModulesTurboModule.web.js → module/turbomodule/NativeNitroModules.web.js} +9 -1
- package/lib/module/turbomodule/NativeNitroModules.web.js.map +1 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/turbomodule/NativeNitroModules.d.ts +7 -0
- package/lib/turbomodule/NativeNitroModules.js +27 -0
- package/lib/turbomodule/NativeNitroModules.web.d.ts +2 -0
- package/lib/turbomodule/NativeNitroModules.web.js +9 -0
- package/lib/typescript/AnyMap.d.ts +20 -0
- package/lib/typescript/BoxedHybridObject.d.ts +13 -0
- package/lib/typescript/BoxedHybridObject.d.ts.map +1 -0
- package/lib/typescript/ModuleNotFoundError.d.ts +7 -0
- package/lib/typescript/ModuleNotFoundError.d.ts.map +1 -1
- package/lib/typescript/NitroModules.d.ts +1 -83
- package/lib/typescript/NitroModules.d.ts.map +1 -1
- package/lib/typescript/NitroModulesProxy.d.ts +59 -0
- package/lib/typescript/NitroModulesProxy.d.ts.map +1 -0
- package/lib/typescript/__tests__/index.test.d.ts +1 -0
- package/lib/typescript/index.d.ts +4 -0
- package/lib/typescript/turbomodule/NativeNitroModules.d.ts +8 -0
- package/lib/typescript/turbomodule/NativeNitroModules.d.ts.map +1 -0
- package/lib/typescript/turbomodule/NativeNitroModules.web.d.ts +3 -0
- package/lib/typescript/turbomodule/NativeNitroModules.web.d.ts.map +1 -0
- package/package.json +9 -1
- package/src/BoxedHybridObject.ts +13 -0
- package/src/ModuleNotFoundError.ts +3 -19
- package/src/NitroModules.ts +2 -108
- package/src/NitroModulesProxy.ts +61 -0
- package/src/turbomodule/NativeNitroModules.ts +48 -0
- package/src/turbomodule/NativeNitroModules.web.ts +16 -0
- package/android/src/main/java/com/margelo/nitro/NitroModulesPackage.java +0 -30
- package/cpp/turbomodule/NativeNitroModules.cpp +0 -146
- package/cpp/turbomodule/NativeNitroModules.h +0 -8
- package/cpp/turbomodule/NativeNitroModules.hpp +0 -38
- package/cpp/turbomodule/RegisterNativeNitroModules.cpp +0 -33
- package/cpp/turbomodule/RegisterNativeNitroModules.hpp +0 -21
- package/ios/turbomodule/NitroModuleOnLoad.mm +0 -32
- package/lib/NativeNitroModules.d.ts +0 -16
- package/lib/NativeNitroModules.js +0 -22
- package/lib/NativeNitroModules.web.d.ts +0 -4
- package/lib/NativeNitroModules.web.js +0 -3
- package/lib/NitroModulesTurboModule.d.ts +0 -18
- package/lib/NitroModulesTurboModule.js +0 -23
- package/lib/NitroModulesTurboModule.web.d.ts +0 -1
- package/lib/commonjs/NitroModulesTurboModule.js +0 -34
- package/lib/commonjs/NitroModulesTurboModule.js.map +0 -1
- package/lib/commonjs/NitroModulesTurboModule.web.js +0 -11
- package/lib/commonjs/NitroModulesTurboModule.web.js.map +0 -1
- package/lib/module/NitroModulesTurboModule.js +0 -30
- package/lib/module/NitroModulesTurboModule.js.map +0 -1
- package/lib/module/NitroModulesTurboModule.web.js +0 -7
- package/lib/module/NitroModulesTurboModule.web.js.map +0 -1
- package/lib/typescript/NitroModulesTurboModule.d.ts +0 -19
- package/lib/typescript/NitroModulesTurboModule.d.ts.map +0 -1
- package/lib/typescript/NitroModulesTurboModule.web.d.ts +0 -2
- package/lib/typescript/NitroModulesTurboModule.web.d.ts.map +0 -1
- package/src/NitroModulesTurboModule.ts +0 -50
- package/src/NitroModulesTurboModule.web.ts +0 -7
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { HybridObject } from './HybridObject';
|
|
2
|
+
import type { BoxedHybridObject } from './BoxedHybridObject';
|
|
3
|
+
/**
|
|
4
|
+
* The Proxy class that acts as a main entry point for Nitro Modules in React Native.
|
|
5
|
+
*
|
|
6
|
+
* This is a `HybridObject` on the native side as well, and is expected to be
|
|
7
|
+
* installed into the runtime's `global` via the NativeModule/TurboModule's `install()` function.
|
|
8
|
+
*/
|
|
9
|
+
export interface NitroModulesProxy extends HybridObject {
|
|
10
|
+
/**
|
|
11
|
+
* Create a new instance of the `HybridObject` {@linkcode T}.
|
|
12
|
+
*
|
|
13
|
+
* {@linkcode T} has to be registered beforehand under the name {@linkcode name}
|
|
14
|
+
* in the native Nitro Modules `HybridObjectRegistry`.
|
|
15
|
+
*
|
|
16
|
+
* @param name The name of the `HybridObject` under which it was registered at.
|
|
17
|
+
* @returns An instance of {@linkcode T}
|
|
18
|
+
* @throws an Error if {@linkcode T} has not been registered under the name {@linkcode name}.
|
|
19
|
+
*/
|
|
20
|
+
createHybridObject<T extends HybridObject>(name: string): T;
|
|
21
|
+
/**
|
|
22
|
+
* Returns whether a HybridObject under the given {@linkcode name} is registered, or not.
|
|
23
|
+
*/
|
|
24
|
+
hasHybridObject(name: string): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Get a list of all registered Hybrid Objects.
|
|
27
|
+
*/
|
|
28
|
+
getAllHybridObjectNames(): string[];
|
|
29
|
+
/**
|
|
30
|
+
* Gets the current build type configuration as defined in the `NITRO_DEBUG`
|
|
31
|
+
* preprocessor flag.
|
|
32
|
+
*/
|
|
33
|
+
buildType: 'debug' | 'release';
|
|
34
|
+
/**
|
|
35
|
+
* Boxes the given {@linkcode hybridObject} into a {@linkcode BoxedHybridObject<T>}, which can
|
|
36
|
+
* later be unboxed in a separate Runtime.
|
|
37
|
+
*
|
|
38
|
+
* While Nitro is runtime-agnostic and all `HybridObject`s can be used from a any Runtime,
|
|
39
|
+
* some threading/worklet libraries (like [react-native-worklets-core](https://github.com/margelo/react-native-worklets-core))
|
|
40
|
+
* do not yet support copying over `HybridObject`s as they use newer JSI APIs like `jsi::NativeState`.
|
|
41
|
+
*
|
|
42
|
+
* While those APIs are not yet available, you can still use every Nitro Hybrid Object in a separate
|
|
43
|
+
* Runtime/Worklet context by just boxing it yourself:
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```ts
|
|
47
|
+
* const something = NitroModules.createHybridObject<Something>('Something')
|
|
48
|
+
* const boxed = NitroModules.box(something)
|
|
49
|
+
* const context = Worklets.createContext('DummyContext')
|
|
50
|
+
* context.runAsync(() => {
|
|
51
|
+
* 'worklet'
|
|
52
|
+
* const unboxed = boxed.unbox()
|
|
53
|
+
* console.log(unboxed.name) // --> "Something"
|
|
54
|
+
* })
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
box<T extends HybridObject>(obj: T): BoxedHybridObject<T>;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=NitroModulesProxy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NitroModulesProxy.d.ts","sourceRoot":"","sources":["../../src/NitroModulesProxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAE5D;;;;;GAKG;AACH,MAAM,WAAW,iBAAkB,SAAQ,YAAY;IACrD;;;;;;;;;OASG;IACH,kBAAkB,CAAC,CAAC,SAAS,YAAY,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,CAAA;IAC3D;;OAEG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;IACtC;;OAEG;IACH,uBAAuB,IAAI,MAAM,EAAE,CAAA;IAEnC;;;OAGG;IACH,SAAS,EAAE,OAAO,GAAG,SAAS,CAAA;IAE9B;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,GAAG,CAAC,CAAC,SAAS,YAAY,EAAE,GAAG,EAAE,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAA;CAC1D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=index.test.d.ts.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { NitroModulesProxy } from '../NitroModulesProxy';
|
|
2
|
+
export declare const NitroModules: NitroModulesProxy;
|
|
3
|
+
declare global {
|
|
4
|
+
var __nitroModulesJSICache: {};
|
|
5
|
+
var __nitroDispatcher: {};
|
|
6
|
+
}
|
|
7
|
+
export declare function isRuntimeAlive(): boolean;
|
|
8
|
+
//# sourceMappingURL=NativeNitroModules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NativeNitroModules.d.ts","sourceRoot":"","sources":["../../../src/turbomodule/NativeNitroModules.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AA2B7D,eAAO,MAAM,YAAY,EAA+B,iBAAiB,CAAA;AAQzE,OAAO,CAAC,MAAM,CAAC;IACb,IAAI,sBAAsB,EAAE,EAAE,CAAA;IAC9B,IAAI,iBAAiB,EAAE,EAAE,CAAA;CAC1B;AAED,wBAAgB,cAAc,YAI7B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NativeNitroModules.web.d.ts","sourceRoot":"","sources":["../../../src/turbomodule/NativeNitroModules.web.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,YAAY,IASxB,CAAA;AAED,wBAAgB,cAAc,IAAI,OAAO,CAExC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-nitro-modules",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "Insanely fast native C++, Swift or Kotlin modules with a statically compiled binding layer to JSI.",
|
|
5
5
|
"main": "lib/index",
|
|
6
6
|
"module": "lib/index",
|
|
@@ -147,5 +147,13 @@
|
|
|
147
147
|
}
|
|
148
148
|
]
|
|
149
149
|
]
|
|
150
|
+
},
|
|
151
|
+
"codegenConfig": {
|
|
152
|
+
"name": "NitroModulesSpec",
|
|
153
|
+
"type": "modules",
|
|
154
|
+
"jsSrcsDir": "./src",
|
|
155
|
+
"android": {
|
|
156
|
+
"javaPackageName": "com.margelo.nitro"
|
|
157
|
+
}
|
|
150
158
|
}
|
|
151
159
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { HybridObject } from './HybridObject'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Represents a boxed {@linkcode HybridObject} that can later be unboxed again.
|
|
5
|
+
* This is implemented as a `jsi::HostObject`.
|
|
6
|
+
*/
|
|
7
|
+
export interface BoxedHybridObject<T extends HybridObject> {
|
|
8
|
+
/**
|
|
9
|
+
* Unboxes the {@linkcode HybridObject}.
|
|
10
|
+
* This can be called from a different Runtime than the one it was boxed in.
|
|
11
|
+
*/
|
|
12
|
+
unbox(): T
|
|
13
|
+
}
|
|
@@ -32,20 +32,6 @@ function getFrameworkType(): 'react-native' | 'expo' | 'expo-go' {
|
|
|
32
32
|
|
|
33
33
|
export class ModuleNotFoundError extends Error {
|
|
34
34
|
constructor(cause?: unknown) {
|
|
35
|
-
// TurboModule not found, something went wrong!
|
|
36
|
-
if (global.__turboModuleProxy == null) {
|
|
37
|
-
// TurboModules are not available/new arch is not enabled.
|
|
38
|
-
const message =
|
|
39
|
-
'Failed to get NitroModules: NitroModules require the new architecture to be enabled!'
|
|
40
|
-
const suggestions: string[] = []
|
|
41
|
-
suggestions.push(
|
|
42
|
-
'Enable the new architecture in your app to use NitroModules. (See https://github.com/reactwg/react-native-new-architecture/blob/main/docs/enable-apps.md)'
|
|
43
|
-
)
|
|
44
|
-
const error = messageWithSuggestions(message, suggestions)
|
|
45
|
-
super(error, { cause: cause })
|
|
46
|
-
return
|
|
47
|
-
}
|
|
48
|
-
|
|
49
35
|
const framework = getFrameworkType()
|
|
50
36
|
if (framework === 'expo-go') {
|
|
51
37
|
super(
|
|
@@ -55,17 +41,15 @@ export class ModuleNotFoundError extends Error {
|
|
|
55
41
|
}
|
|
56
42
|
|
|
57
43
|
const message =
|
|
58
|
-
'Failed to get NitroModules: The native "NitroModules"
|
|
44
|
+
'Failed to get NitroModules: The native "NitroModules" Turbo/Native-Module could not be found.'
|
|
59
45
|
const suggestions: string[] = []
|
|
60
46
|
suggestions.push(
|
|
61
47
|
'Make sure react-native-nitro-modules/NitroModules is correctly autolinked (run `npx react-native config` to verify)'
|
|
62
48
|
)
|
|
63
49
|
suggestions.push(
|
|
64
|
-
'Make sure you enabled the new architecture (TurboModules) and CodeGen properly generated the "NativeNitroModules"/
|
|
65
|
-
)
|
|
66
|
-
suggestions.push(
|
|
67
|
-
'Make sure you are using react-native 0.74.0 or higher, because NitroModules are built with C++ TurboModules.'
|
|
50
|
+
'Make sure you enabled the new architecture (TurboModules) and CodeGen properly generated the "NativeNitroModules"/NitroModules specs. See https://github.com/reactwg/react-native-new-architecture/blob/main/docs/enable-apps.md'
|
|
68
51
|
)
|
|
52
|
+
suggestions.push('Make sure you are using react-native 0.74.0 or higher.')
|
|
69
53
|
suggestions.push('Make sure you rebuilt the app.')
|
|
70
54
|
if (framework === 'expo') {
|
|
71
55
|
suggestions.push('Make sure you ran `expo prebuild`.')
|
package/src/NitroModules.ts
CHANGED
|
@@ -1,108 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Represents a boxed {@linkcode HybridObject} that can later be unboxed again.
|
|
6
|
-
* This is implemented as a `jsi::HostObject`.
|
|
7
|
-
*/
|
|
8
|
-
export interface BoxedHybridObject<T extends HybridObject> {
|
|
9
|
-
/**
|
|
10
|
-
* Unboxes the {@linkcode HybridObject}.
|
|
11
|
-
* This can be called from a different Runtime than the one it was boxed in.
|
|
12
|
-
*/
|
|
13
|
-
unbox(): T
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* A lazy proxy for initializing Nitro Modules HybridObjects.
|
|
18
|
-
*/
|
|
19
|
-
export const NitroModules = {
|
|
20
|
-
/**
|
|
21
|
-
* Create a new instance of the `HybridObject` {@linkcode T}.
|
|
22
|
-
*
|
|
23
|
-
* {@linkcode T} has to be registered beforehand under the name {@linkcode name}
|
|
24
|
-
* in the native Nitro Modules `HybridObjectRegistry`.
|
|
25
|
-
*
|
|
26
|
-
* @param name The name of the `HybridObject` under which it was registered at.
|
|
27
|
-
* @returns An instance of {@linkcode T}
|
|
28
|
-
* @throws an Error if {@linkcode T} has not been registered under the name {@linkcode name}.
|
|
29
|
-
*/
|
|
30
|
-
createHybridObject<T extends HybridObject<any>>(name: string): T {
|
|
31
|
-
const nitro = getNativeNitroModules()
|
|
32
|
-
const instance = nitro.createHybridObject(name)
|
|
33
|
-
return instance as T
|
|
34
|
-
},
|
|
35
|
-
/**
|
|
36
|
-
* Get a list of all registered Hybrid Objects.
|
|
37
|
-
*/
|
|
38
|
-
getAllHybridObjectNames(): string[] {
|
|
39
|
-
const nitro = getNativeNitroModules()
|
|
40
|
-
return nitro.getAllHybridObjectNames()
|
|
41
|
-
},
|
|
42
|
-
/**
|
|
43
|
-
* Returns whether a HybridObject under the given {@linkcode name} is registered, or not.
|
|
44
|
-
*/
|
|
45
|
-
hasHybridObject(name: string): boolean {
|
|
46
|
-
const nitro = getNativeNitroModules()
|
|
47
|
-
return nitro.hasHybridObject(name)
|
|
48
|
-
},
|
|
49
|
-
/**
|
|
50
|
-
* Returns whether the given {@linkcode object} has a `NativeState` or not.
|
|
51
|
-
*
|
|
52
|
-
* This can be a quick way to check if an object is a valid {@linkcode HybridObject},
|
|
53
|
-
* and has not yet been disposed.
|
|
54
|
-
* @example
|
|
55
|
-
* ```ts
|
|
56
|
-
* const someObject = NitroModules.createHybridObject<Some>('Some')
|
|
57
|
-
* console.log(NitroModules.hasNativeState(someObject)) // -> true
|
|
58
|
-
* someObject.dispose()
|
|
59
|
-
* console.log(NitroModules.hasNativeState(someObject)) // -> false
|
|
60
|
-
* ```
|
|
61
|
-
*/
|
|
62
|
-
hasNativeState(object: object): boolean {
|
|
63
|
-
const nitro = getNativeNitroModules()
|
|
64
|
-
return nitro.hasNativeState(object)
|
|
65
|
-
},
|
|
66
|
-
/**
|
|
67
|
-
* Forcefully removes the `NativeState` of the given {@linkcode object}.
|
|
68
|
-
*/
|
|
69
|
-
removeNativeState(object: object): void {
|
|
70
|
-
const nitro = getNativeNitroModules()
|
|
71
|
-
nitro.removeNativeState(object)
|
|
72
|
-
},
|
|
73
|
-
/**
|
|
74
|
-
* Gets the current build type configuration as defined in the `NITRO_DEBUG`
|
|
75
|
-
* preprocessor flag.
|
|
76
|
-
*/
|
|
77
|
-
get buildType(): 'debug' | 'release' {
|
|
78
|
-
const nitro = getNativeNitroModules()
|
|
79
|
-
return nitro.buildType
|
|
80
|
-
},
|
|
81
|
-
/**
|
|
82
|
-
* Boxes the given {@linkcode hybridObject} into a {@linkcode BoxedHybridObject<T>}, which can
|
|
83
|
-
* later be unboxed in a separate Runtime.
|
|
84
|
-
*
|
|
85
|
-
* While Nitro is runtime-agnostic and all `HybridObject`s can be used from a any Runtime,
|
|
86
|
-
* some threading/worklet libraries (like [react-native-worklets-core](https://github.com/margelo/react-native-worklets-core))
|
|
87
|
-
* do not yet support copying over `HybridObject`s as they use newer JSI APIs like `jsi::NativeState`.
|
|
88
|
-
*
|
|
89
|
-
* While those APIs are not yet available, you can still use every Nitro Hybrid Object in a separate
|
|
90
|
-
* Runtime/Worklet context by just boxing it yourself:
|
|
91
|
-
*
|
|
92
|
-
* @example
|
|
93
|
-
* ```ts
|
|
94
|
-
* const something = NitroModules.createHybridObject<Something>('Something')
|
|
95
|
-
* const boxed = NitroModules.box(something)
|
|
96
|
-
* const context = Worklets.createContext('DummyContext')
|
|
97
|
-
* context.runAsync(() => {
|
|
98
|
-
* 'worklet'
|
|
99
|
-
* const unboxed = boxed.unbox()
|
|
100
|
-
* console.log(unboxed.name) // --> "Something"
|
|
101
|
-
* })
|
|
102
|
-
* ```
|
|
103
|
-
*/
|
|
104
|
-
box<T extends HybridObject>(hybridObject: T): BoxedHybridObject<T> {
|
|
105
|
-
const nitro = getNativeNitroModules()
|
|
106
|
-
return nitro.box(hybridObject) as BoxedHybridObject<T>
|
|
107
|
-
},
|
|
108
|
-
}
|
|
1
|
+
// Re-exports the platform specific `NitroModulesProxy` (or a stub-implementation if not found)
|
|
2
|
+
export * from './turbomodule/NativeNitroModules'
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { HybridObject } from './HybridObject'
|
|
2
|
+
import type { BoxedHybridObject } from './BoxedHybridObject'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The Proxy class that acts as a main entry point for Nitro Modules in React Native.
|
|
6
|
+
*
|
|
7
|
+
* This is a `HybridObject` on the native side as well, and is expected to be
|
|
8
|
+
* installed into the runtime's `global` via the NativeModule/TurboModule's `install()` function.
|
|
9
|
+
*/
|
|
10
|
+
export interface NitroModulesProxy extends HybridObject {
|
|
11
|
+
/**
|
|
12
|
+
* Create a new instance of the `HybridObject` {@linkcode T}.
|
|
13
|
+
*
|
|
14
|
+
* {@linkcode T} has to be registered beforehand under the name {@linkcode name}
|
|
15
|
+
* in the native Nitro Modules `HybridObjectRegistry`.
|
|
16
|
+
*
|
|
17
|
+
* @param name The name of the `HybridObject` under which it was registered at.
|
|
18
|
+
* @returns An instance of {@linkcode T}
|
|
19
|
+
* @throws an Error if {@linkcode T} has not been registered under the name {@linkcode name}.
|
|
20
|
+
*/
|
|
21
|
+
createHybridObject<T extends HybridObject>(name: string): T
|
|
22
|
+
/**
|
|
23
|
+
* Returns whether a HybridObject under the given {@linkcode name} is registered, or not.
|
|
24
|
+
*/
|
|
25
|
+
hasHybridObject(name: string): boolean
|
|
26
|
+
/**
|
|
27
|
+
* Get a list of all registered Hybrid Objects.
|
|
28
|
+
*/
|
|
29
|
+
getAllHybridObjectNames(): string[]
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Gets the current build type configuration as defined in the `NITRO_DEBUG`
|
|
33
|
+
* preprocessor flag.
|
|
34
|
+
*/
|
|
35
|
+
buildType: 'debug' | 'release'
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Boxes the given {@linkcode hybridObject} into a {@linkcode BoxedHybridObject<T>}, which can
|
|
39
|
+
* later be unboxed in a separate Runtime.
|
|
40
|
+
*
|
|
41
|
+
* While Nitro is runtime-agnostic and all `HybridObject`s can be used from a any Runtime,
|
|
42
|
+
* some threading/worklet libraries (like [react-native-worklets-core](https://github.com/margelo/react-native-worklets-core))
|
|
43
|
+
* do not yet support copying over `HybridObject`s as they use newer JSI APIs like `jsi::NativeState`.
|
|
44
|
+
*
|
|
45
|
+
* While those APIs are not yet available, you can still use every Nitro Hybrid Object in a separate
|
|
46
|
+
* Runtime/Worklet context by just boxing it yourself:
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```ts
|
|
50
|
+
* const something = NitroModules.createHybridObject<Something>('Something')
|
|
51
|
+
* const boxed = NitroModules.box(something)
|
|
52
|
+
* const context = Worklets.createContext('DummyContext')
|
|
53
|
+
* context.runAsync(() => {
|
|
54
|
+
* 'worklet'
|
|
55
|
+
* const unboxed = boxed.unbox()
|
|
56
|
+
* console.log(unboxed.name) // --> "Something"
|
|
57
|
+
* })
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
box<T extends HybridObject>(obj: T): BoxedHybridObject<T>
|
|
61
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { TurboModule } from 'react-native'
|
|
2
|
+
import { TurboModuleRegistry } from 'react-native'
|
|
3
|
+
import { ModuleNotFoundError } from '../ModuleNotFoundError'
|
|
4
|
+
import type { NitroModulesProxy } from '../NitroModulesProxy'
|
|
5
|
+
|
|
6
|
+
interface Spec extends TurboModule {
|
|
7
|
+
/**
|
|
8
|
+
* Installs `NitroModulesProxy` into this JS Runtime's `global`.
|
|
9
|
+
* Also sets up a Dispatcher for the main JS Runtime.
|
|
10
|
+
* @returns A `string` error message if this function failed to run, or `undefined` if everything went successful.
|
|
11
|
+
*/
|
|
12
|
+
install(): string | undefined
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// 1. Get (and initialize) the TurboModule
|
|
16
|
+
let turboModule: Spec | undefined
|
|
17
|
+
try {
|
|
18
|
+
turboModule = TurboModuleRegistry.getEnforcing<Spec>('NitroModules')
|
|
19
|
+
} catch (e) {
|
|
20
|
+
throw new ModuleNotFoundError(e)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// 2. Install Dispatcher and install `NitroModulesProxy` into the Runtime's `global`
|
|
24
|
+
const errorMessage = turboModule.install()
|
|
25
|
+
if (errorMessage != null) {
|
|
26
|
+
throw new Error(`Failed to install Nitro: ${errorMessage}`)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// 3. Find `NitroModulesProxy` in `global`
|
|
30
|
+
// @ts-expect-error
|
|
31
|
+
export const NitroModules = global.NitroModulesProxy as NitroModulesProxy
|
|
32
|
+
if (NitroModules == null) {
|
|
33
|
+
const cause = new Error(
|
|
34
|
+
'NitroModules was installed, but `global.NitroModulesProxy` was null!'
|
|
35
|
+
)
|
|
36
|
+
throw new ModuleNotFoundError(cause)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
declare global {
|
|
40
|
+
var __nitroModulesJSICache: {}
|
|
41
|
+
var __nitroDispatcher: {}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function isRuntimeAlive() {
|
|
45
|
+
const cache = global.__nitroModulesJSICache
|
|
46
|
+
const dispatcher = global.__nitroDispatcher
|
|
47
|
+
return cache != null && dispatcher != null
|
|
48
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Platform } from 'react-native'
|
|
2
|
+
|
|
3
|
+
export const NitroModules = new Proxy(
|
|
4
|
+
{},
|
|
5
|
+
{
|
|
6
|
+
get: () => {
|
|
7
|
+
throw new Error(
|
|
8
|
+
`Native NitroModules are not available on ${Platform.OS}! Make sure you're not calling getNativeNitroModules() in a ${Platform.OS} (.${Platform.OS}.ts) environment.`
|
|
9
|
+
)
|
|
10
|
+
},
|
|
11
|
+
}
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
export function isRuntimeAlive(): boolean {
|
|
15
|
+
return false
|
|
16
|
+
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
package com.margelo.nitro;
|
|
2
|
-
|
|
3
|
-
import android.util.Log;
|
|
4
|
-
import androidx.annotation.Nullable;
|
|
5
|
-
|
|
6
|
-
import com.facebook.react.bridge.NativeModule;
|
|
7
|
-
import com.facebook.react.bridge.ReactApplicationContext;
|
|
8
|
-
import com.facebook.react.module.model.ReactModuleInfoProvider;
|
|
9
|
-
import com.facebook.react.TurboReactPackage;
|
|
10
|
-
|
|
11
|
-
import java.util.HashMap;
|
|
12
|
-
|
|
13
|
-
public class NitroModulesPackage extends TurboReactPackage {
|
|
14
|
-
static {
|
|
15
|
-
JNIOnLoad.initializeNativeNitro();
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
@Nullable
|
|
19
|
-
@Override
|
|
20
|
-
public NativeModule getModule(String name, ReactApplicationContext reactContext) {
|
|
21
|
-
return null;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
@Override
|
|
25
|
-
public ReactModuleInfoProvider getReactModuleInfoProvider() {
|
|
26
|
-
return () -> {
|
|
27
|
-
return new HashMap<>();
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
}
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// NativeNitroModules.cpp
|
|
3
|
-
// NitroModules
|
|
4
|
-
//
|
|
5
|
-
// Created by Marc Rousavy on 21.06.24.
|
|
6
|
-
//
|
|
7
|
-
|
|
8
|
-
#include "NativeNitroModules.hpp"
|
|
9
|
-
#include "BoxedHybridObject.hpp"
|
|
10
|
-
#include "CallInvokerDispatcher.hpp"
|
|
11
|
-
#include "Dispatcher.hpp"
|
|
12
|
-
#include "HybridObjectRegistry.hpp"
|
|
13
|
-
#include "NitroDefines.hpp"
|
|
14
|
-
|
|
15
|
-
namespace facebook::react {
|
|
16
|
-
|
|
17
|
-
using namespace margelo::nitro;
|
|
18
|
-
|
|
19
|
-
NativeNitroModules::NativeNitroModules(std::shared_ptr<CallInvoker> jsInvoker)
|
|
20
|
-
: TurboModule(kModuleName, jsInvoker), _callInvoker(jsInvoker) {}
|
|
21
|
-
|
|
22
|
-
jsi::Value NativeNitroModules::get(jsi::Runtime& runtime, const jsi::PropNameID& propName) {
|
|
23
|
-
std::string name = propName.utf8(runtime);
|
|
24
|
-
|
|
25
|
-
if (name == "install") {
|
|
26
|
-
return jsi::Function::createFromHostFunction(
|
|
27
|
-
runtime, jsi::PropNameID::forUtf8(runtime, "install"), 0,
|
|
28
|
-
[this](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args, size_t count) -> jsi::Value {
|
|
29
|
-
install(runtime);
|
|
30
|
-
return jsi::Value::undefined();
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
if (name == "createHybridObject") {
|
|
34
|
-
return jsi::Function::createFromHostFunction(
|
|
35
|
-
runtime, jsi::PropNameID::forUtf8(runtime, "createHybridObject"), 1,
|
|
36
|
-
[this](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args, size_t count) -> jsi::Value {
|
|
37
|
-
#ifdef NITRO_DEBUG
|
|
38
|
-
if (count != 1) [[unlikely]] {
|
|
39
|
-
throw jsi::JSError(runtime,
|
|
40
|
-
"NitroModules.createHybridObject(..) expects 1 argument, but " + std::to_string(count) + " were supplied!");
|
|
41
|
-
}
|
|
42
|
-
#endif
|
|
43
|
-
jsi::String objectName = args[0].asString(runtime);
|
|
44
|
-
return createHybridObject(runtime, objectName);
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
if (name == "hasHybridObject") {
|
|
48
|
-
return jsi::Function::createFromHostFunction(
|
|
49
|
-
runtime, jsi::PropNameID::forUtf8(runtime, "hasHybridObject"), 1,
|
|
50
|
-
[this](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args, size_t count) -> jsi::Value {
|
|
51
|
-
#ifdef NITRO_DEBUG
|
|
52
|
-
if (count != 1) [[unlikely]] {
|
|
53
|
-
throw jsi::JSError(runtime,
|
|
54
|
-
"NitroModules.hasHybridObject(..) expects 1 argument (name), but received " + std::to_string(count) + "!");
|
|
55
|
-
}
|
|
56
|
-
#endif
|
|
57
|
-
jsi::String objectName = args[0].asString(runtime);
|
|
58
|
-
return hasHybridObject(runtime, objectName);
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
if (name == "getAllHybridObjectNames") {
|
|
62
|
-
return jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, "getAllHybridObjectNames"), 0,
|
|
63
|
-
[this](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args,
|
|
64
|
-
size_t count) -> jsi::Value { return getAllHybridObjectNames(runtime); });
|
|
65
|
-
}
|
|
66
|
-
if (name == "hasNativeState") {
|
|
67
|
-
return jsi::Function::createFromHostFunction(
|
|
68
|
-
runtime, jsi::PropNameID::forUtf8(runtime, "hasNativeState"), 1,
|
|
69
|
-
[](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args, size_t count) -> jsi::Value {
|
|
70
|
-
jsi::Object object = args[0].asObject(runtime);
|
|
71
|
-
bool has = object.hasNativeState(runtime) && object.getNativeState(runtime) != nullptr;
|
|
72
|
-
return jsi::Value(has);
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
if (name == "removeNativeState") {
|
|
76
|
-
return jsi::Function::createFromHostFunction(
|
|
77
|
-
runtime, jsi::PropNameID::forUtf8(runtime, "removeNativeState"), 1,
|
|
78
|
-
[](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args, size_t count) -> jsi::Value {
|
|
79
|
-
jsi::Object object = args[0].asObject(runtime);
|
|
80
|
-
object.setNativeState(runtime, nullptr);
|
|
81
|
-
return jsi::Value::undefined();
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
if (name == "box") {
|
|
85
|
-
return jsi::Function::createFromHostFunction(
|
|
86
|
-
runtime, jsi::PropNameID::forUtf8(runtime, "box"), 1,
|
|
87
|
-
[](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args, size_t count) -> jsi::Value {
|
|
88
|
-
jsi::Object object = args[0].asObject(runtime);
|
|
89
|
-
#ifdef NITRO_DEBUG
|
|
90
|
-
if (!object.hasNativeState(runtime)) {
|
|
91
|
-
std::string stringified = args[0].toString(runtime).utf8(runtime);
|
|
92
|
-
throw std::runtime_error("Cannot box object " + stringified + " - it does not have a NativeState!");
|
|
93
|
-
}
|
|
94
|
-
#endif
|
|
95
|
-
|
|
96
|
-
std::shared_ptr<jsi::NativeState> nativeState = object.getNativeState(runtime);
|
|
97
|
-
std::shared_ptr<HybridObject> maybeHybridObject = std::dynamic_pointer_cast<HybridObject>(nativeState);
|
|
98
|
-
if (maybeHybridObject == nullptr) {
|
|
99
|
-
std::string stringified = args[0].toString(runtime).utf8(runtime);
|
|
100
|
-
throw std::runtime_error("Cannot box object " + stringified + " - it has a NativeState, but it's not a HybridObject!");
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
auto boxed = std::make_shared<BoxedHybridObject>(maybeHybridObject);
|
|
104
|
-
return jsi::Object::createFromHostObject(runtime, boxed);
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
if (name == "buildType") {
|
|
108
|
-
#ifdef NITRO_DEBUG
|
|
109
|
-
return jsi::String::createFromAscii(runtime, "debug");
|
|
110
|
-
#else
|
|
111
|
-
return jsi::String::createFromAscii(runtime, "release");
|
|
112
|
-
#endif
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
return jsi::Value::undefined();
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
void NativeNitroModules::install(jsi::Runtime& runtime) {
|
|
119
|
-
// Installs the global Dispatcher mechanism into this Runtime.
|
|
120
|
-
// This allows creating Promises and calling back to JS.
|
|
121
|
-
auto dispatcher = std::make_shared<CallInvokerDispatcher>(_callInvoker);
|
|
122
|
-
Dispatcher::installRuntimeGlobalDispatcher(runtime, dispatcher);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
jsi::Value NativeNitroModules::createHybridObject(jsi::Runtime& runtime, const jsi::String& hybridObjectName) {
|
|
126
|
-
auto name = hybridObjectName.utf8(runtime);
|
|
127
|
-
auto hybridObject = HybridObjectRegistry::createHybridObject(name);
|
|
128
|
-
return hybridObject->toObject(runtime);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
jsi::Value NativeNitroModules::hasHybridObject(jsi::Runtime& runtime, const jsi::String& hybridObjectName) {
|
|
132
|
-
std::string name = hybridObjectName.utf8(runtime);
|
|
133
|
-
bool exists = HybridObjectRegistry::hasHybridObject(name);
|
|
134
|
-
return exists;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
jsi::Value NativeNitroModules::getAllHybridObjectNames(jsi::Runtime& runtime) {
|
|
138
|
-
std::vector<std::string> keys = HybridObjectRegistry::getAllHybridObjectNames();
|
|
139
|
-
jsi::Array array(runtime, keys.size());
|
|
140
|
-
for (size_t i = 0; i < keys.size(); i++) {
|
|
141
|
-
array.setValueAtIndex(runtime, i, jsi::String::createFromUtf8(runtime, keys[i]));
|
|
142
|
-
}
|
|
143
|
-
return array;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
} // namespace facebook::react
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// NativeNitroModules.hpp
|
|
3
|
-
// NitroModules
|
|
4
|
-
//
|
|
5
|
-
// Created by Marc Rousavy on 21.06.24.
|
|
6
|
-
//
|
|
7
|
-
|
|
8
|
-
#pragma once
|
|
9
|
-
|
|
10
|
-
#include <ReactCommon/TurboModule.h>
|
|
11
|
-
|
|
12
|
-
namespace facebook::react {
|
|
13
|
-
|
|
14
|
-
using namespace facebook;
|
|
15
|
-
|
|
16
|
-
// The base C++-based TurboModule. This is the entry point where all nitro modules get initialized.
|
|
17
|
-
class NativeNitroModules : public TurboModule {
|
|
18
|
-
public:
|
|
19
|
-
explicit NativeNitroModules(std::shared_ptr<CallInvoker> jsInvoker);
|
|
20
|
-
|
|
21
|
-
public:
|
|
22
|
-
jsi::Value get(jsi::Runtime& runtime, const jsi::PropNameID& propName) override;
|
|
23
|
-
|
|
24
|
-
// Setup
|
|
25
|
-
void install(jsi::Runtime& runtime);
|
|
26
|
-
// Hybrid Objects stuff
|
|
27
|
-
jsi::Value createHybridObject(jsi::Runtime& runtime, const jsi::String& hybridObjectName);
|
|
28
|
-
jsi::Value hasHybridObject(jsi::Runtime& runtime, const jsi::String& hybridObjectName);
|
|
29
|
-
jsi::Value getAllHybridObjectNames(jsi::Runtime& runtime);
|
|
30
|
-
|
|
31
|
-
public:
|
|
32
|
-
constexpr static auto kModuleName = "NitroModulesCxx";
|
|
33
|
-
|
|
34
|
-
private:
|
|
35
|
-
std::shared_ptr<CallInvoker> _callInvoker;
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
} // namespace facebook::react
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// RegisterNativeNitroModules.cpp
|
|
3
|
-
// DoubleConversion
|
|
4
|
-
//
|
|
5
|
-
// Created by Marc Rousavy on 21.06.24.
|
|
6
|
-
//
|
|
7
|
-
|
|
8
|
-
#include "RegisterNativeNitroModules.hpp"
|
|
9
|
-
#include "NativeNitroModules.hpp"
|
|
10
|
-
#include <memory>
|
|
11
|
-
#include <string>
|
|
12
|
-
|
|
13
|
-
#if __has_include(<ReactCommon/CallInvoker.h>)
|
|
14
|
-
// Android style imports
|
|
15
|
-
#include <ReactCommon/CallInvoker.h>
|
|
16
|
-
#include <ReactCommon/CxxTurboModuleUtils.h>
|
|
17
|
-
#else
|
|
18
|
-
// iOS style imports
|
|
19
|
-
#include <React-callinvoker/ReactCommon/CallInvoker.h>
|
|
20
|
-
#include <ReactCommon/ReactCommon/CxxTurboModuleUtils.h>
|
|
21
|
-
#endif
|
|
22
|
-
|
|
23
|
-
namespace margelo::nitro {
|
|
24
|
-
|
|
25
|
-
using namespace facebook;
|
|
26
|
-
|
|
27
|
-
void RegisterNativeNitroModules::registerNativeNitroModules() {
|
|
28
|
-
react::registerCxxModuleToGlobalModuleMap(
|
|
29
|
-
std::string(react::NativeNitroModules::kModuleName),
|
|
30
|
-
[&](std::shared_ptr<react::CallInvoker> jsInvoker) { return std::make_shared<react::NativeNitroModules>(jsInvoker); });
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
} // namespace margelo::nitro
|