-
Notifications
You must be signed in to change notification settings - Fork 7
Enable multiple Node-API hosting JS engines / runtimes to share the global Node-API functions #329
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
6f9356d to
f79a30b
Compare
|
Wow, I really need this capability. And I like the "wrap" mechanisms; they're very elegant for this scenario.
From my perspective, using
I agree that releasing the corresponding |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds multi-host support to weak-node-api, enabling multiple Node-API implementations to coexist in a single process. The implementation wraps opaque Node-API pointers (napi_env, napi_threadsafe_function, napi_async_cleanup_hook_handle) with metadata tracking which host owns them, allowing proper delegation of API calls to the correct implementation.
Key changes:
- Introduces
WeakNodeApiMultiHostclass with wrapper mechanism for opaque Node-API types - Generates multi-host header and source files alongside existing weak-node-api files
- Adds comprehensive test coverage for multi-host scenarios including host lifecycle and wrapped pointer handling
Reviewed Changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
packages/weak-node-api/tests/test_multi_host.cpp |
Comprehensive test suite validating multi-host injection, call routing, host lifecycle, and wrapped opaque pointer handling |
packages/weak-node-api/tests/CMakeLists.txt |
Adds new multi-host test file to the build configuration |
packages/weak-node-api/scripts/generators/multi-host.ts |
Code generator for multi-host header and implementation, including wrapper creation and call delegation logic |
packages/weak-node-api/scripts/generate-weak-node-api.ts |
Updates generator to produce multi-host files with documentation headers |
packages/weak-node-api/CMakeLists.txt |
Includes generated multi-host source and header files in the build |
packages/weak-node-api/.gitignore |
Simplifies ignore pattern to cover all generated files |
| struct WeakNodeApiMultiHost : WeakNodeApiHost { | ||
| template <typename T> struct Wrapped { | ||
| static_assert(std::is_same<T, napi_env>::value || |
Copilot
AI
Nov 11, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error message in the static_assert mentions node_api_basic_env as a valid type, but the static_assert conditions only check for napi_env, napi_threadsafe_function, and napi_async_cleanup_hook_handle. Either add a check for node_api_basic_env or remove it from the error message. Note that node_api_basic_env is aliased to napi_env in Node-API, so the current check may be intentionally covering both types, but the error message should clarify this.
| static_assert(std::is_same<T, napi_env>::value || | |
| static_assert(std::is_same<T, napi_env>::value || | |
| std::is_same<T, node_api_basic_env>::value || |
| const output = ` | ||
| /** | ||
| * @file ${fileName} | ||
| * ${headingComment | ||
| .trim() | ||
| .split("\n") | ||
| .map((l) => l.trim()) | ||
| .join("\n* ")} | ||
| * | ||
| * @note This file is generated - don't edit it directly | ||
| */ | ||
| ${generated} | ||
| `; |
Copilot
AI
Nov 11, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The template literal for output has inconsistent indentation with leading whitespace on each line that will be included in the generated files. Consider using a dedent utility or adjusting the template literal to ensure clean output without unwanted leading spaces.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not an issue, as this is ran through clang-format eventually.
This is my suggestion for adding "multi-host" support to
weak-node-api, enabling multiple engines implementing Node-API to co-exist and share the Node-API function namespace. While not needed specifically for bringing Node-API to React Native adding this could makeweak-node-apimore applicable in other scenarios where multiple engines implementing Node-API share a single process.I'm proposing adding mechanisms to "wrap" the opaque pointers of specific Node-API implementors with:
Where
Tis constrained to one of:napi_envnode_api_basic_env(an alias fornapi_envwith slightly altered semantics)napi_threadsafe_functionnapi_async_cleanup_hook_handleThese
Wrappedobjects can then be passed around like their respective opaque pointers and "unwrapped" in the internal implementation of the "multi host" implementation of Node-API functions.Wrappedobjects are created calling one of these instance methods onWeakNodeApiMultiHost:These functions are called internally in
napi_create_threadsafe_functionandnapi_add_async_cleanup_hook.Usage
WeakNodeApiMultiHost(callingmulti_host.wrap(original_env, host);)react-native-node-api/packages/weak-node-api/tests/test_multi_host.cpp
Lines 18 to 52 in f79a30b
Open questions
std::functioninstead of raw function pointers for all (or some) of theWeakNodeApiHostmembers? This would allow capturing lambdas, making it much easier to provide a meaningful implementation of for examplenapi_module_register.Wrappedobjects be owned by theWeakNodeApiMultiHostobject (at least for now), but could we make memory management more efficient to release theWrapped<T>before theWeakNodeApiMultiHostdeletion: Innapi_remove_async_cleanup_hookor some of thenapi_*_threadsafe_functionfunctions?Generated code
Below are samples from the generated code:
napi_create_objectimplementationnapi_create_threadsafe_functionandnapi_add_async_cleanup_hookimplementationsNotice the calls to
wrap, wrapping their opaque "out" pointers.