Skip to content

Commit 5b51864

Browse files
authored
src: enable wrapping Napi namespace with custom namespace (#1135)
Enable support for a `NAPI_CPP_CUSTOM_NAMESPACE` that would wrap the `Napi` namespace in a custom namespace. This can be helpful when there are multiple parts of a compiled shared library or executable that depend on `node-addon-api`, but different versions of it. In order to avoid symbol conflicts in these cases, namespacing can be used to make sure that the linker would not merge definitions that the compiler potentially generates for the node-addon-api methods.
1 parent c54aeef commit 5b51864

File tree

8 files changed

+68
-19
lines changed

8 files changed

+68
-19
lines changed

napi-inl.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818

1919
namespace Napi {
2020

21+
#ifdef NAPI_CPP_CUSTOM_NAMESPACE
22+
namespace NAPI_CPP_CUSTOM_NAMESPACE {
23+
#endif
24+
2125
// Helpers to handle functions exposed from C++.
2226
namespace details {
2327

@@ -6245,6 +6249,10 @@ bool Env::CleanupHook<Hook, Arg>::IsEmpty() const {
62456249
}
62466250
#endif // NAPI_VERSION > 2
62476251

6252+
#ifdef NAPI_CPP_CUSTOM_NAMESPACE
6253+
} // namespace NAPI_CPP_CUSTOM_NAMESPACE
6254+
#endif
6255+
62486256
} // namespace Napi
62496257

62506258
#endif // SRC_NAPI_INL_H_

napi.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,18 @@ static_assert(sizeof(char16_t) == sizeof(wchar_t), "Size mismatch between char16
140140
////////////////////////////////////////////////////////////////////////////////
141141
namespace Napi {
142142

143+
#ifdef NAPI_CPP_CUSTOM_NAMESPACE
144+
// NAPI_CPP_CUSTOM_NAMESPACE can be #define'd per-addon to avoid symbol
145+
// conflicts between different instances of node-addon-api
146+
147+
// First dummy definition of the namespace to make sure that Napi::(name) still
148+
// refers to the right things inside this file.
149+
namespace NAPI_CPP_CUSTOM_NAMESPACE {}
150+
using namespace NAPI_CPP_CUSTOM_NAMESPACE;
151+
152+
namespace NAPI_CPP_CUSTOM_NAMESPACE {
153+
#endif
154+
143155
// Forward declarations
144156
class Env;
145157
class Value;
@@ -2979,6 +2991,10 @@ namespace Napi {
29792991
};
29802992
#endif // NAPI_VERSION > 5
29812993

2994+
#ifdef NAPI_CPP_CUSTOM_NAMESPACE
2995+
} // namespace NAPI_CPP_CUSTOM_NAMESPACE
2996+
#endif
2997+
29822998
} // namespace Napi
29832999

29843000
// Inline implementations of all the above class methods are included here.

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,6 @@
323323
"name": "WenheLI",
324324
"url": "https://github.com/WenheLI"
325325
},
326-
327326
{
328327
"name": "Yohei Kishimoto",
329328
"url": "https://github.com/morokosi"

test/binding.gyp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,5 +114,11 @@
114114
'sources': ['>@(build_sources_swallowexcept)'],
115115
'defines': ['NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS']
116116
},
117+
{
118+
'target_name': 'binding_custom_namespace',
119+
'includes': ['../noexcept.gypi'],
120+
'sources': ['>@(build_sources)'],
121+
'defines': ['NAPI_CPP_CUSTOM_NAMESPACE=cstm']
122+
},
117123
],
118124
}

test/common/index.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ exports.runTest = async function (test, buildType, buildPathRoot = process.env.B
8181
const bindings = [
8282
path.join(buildPathRoot, `../build/${buildType}/binding.node`),
8383
path.join(buildPathRoot, `../build/${buildType}/binding_noexcept.node`),
84-
path.join(buildPathRoot, `../build/${buildType}/binding_noexcept_maybe.node`)
84+
path.join(buildPathRoot, `../build/${buildType}/binding_noexcept_maybe.node`),
85+
path.join(buildPathRoot, `../build/${buildType}/binding_custom_namespace.node`)
8586
].map(it => require.resolve(it));
8687

8788
for (const item of bindings) {
@@ -96,7 +97,8 @@ exports.runTestWithBindingPath = async function (test, buildType, buildPathRoot
9697
const bindings = [
9798
path.join(buildPathRoot, `../build/${buildType}/binding.node`),
9899
path.join(buildPathRoot, `../build/${buildType}/binding_noexcept.node`),
99-
path.join(buildPathRoot, `../build/${buildType}/binding_noexcept_maybe.node`)
100+
path.join(buildPathRoot, `../build/${buildType}/binding_noexcept_maybe.node`),
101+
path.join(buildPathRoot, `../build/${buildType}/binding_custom_namespace.node`)
100102
].map(it => require.resolve(it));
101103

102104
for (const item of bindings) {

test/common/test_helper.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33

44
namespace Napi {
55

6+
// Needs this here since the MaybeUnwrap() functions need to be in the
7+
// same namespace as their arguments for C++ argument-dependent lookup
8+
#ifdef NAPI_CPP_CUSTOM_NAMESPACE
9+
namespace NAPI_CPP_CUSTOM_NAMESPACE {
10+
#endif
11+
612
// Use this when a variable or parameter is unused in order to explicitly
713
// silence a compiler warning about that.
814
template <typename T>
@@ -58,4 +64,8 @@ inline bool MaybeUnwrapTo(MaybeOrValue<T> maybe, T* out) {
5864
#endif
5965
}
6066

67+
#ifdef NAPI_CPP_CUSTOM_NAMESPACE
68+
} // namespace NAPI_CPP_CUSTOM_NAMESPACE
69+
#endif
70+
6171
} // namespace Napi

test/error_terminating_environment.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ test(`./build/${buildType}/binding.node`, true);
7070
test(`./build/${buildType}/binding_noexcept.node`, true);
7171
test(`./build/${buildType}/binding_swallowexcept.node`, false);
7272
test(`./build/${buildType}/binding_swallowexcept_noexcept.node`, false);
73+
test(`./build/${buildType}/binding_custom_namespace.node`, true);
7374

7475
function test(bindingPath, process_should_abort) {
7576
const number_of_test_cases = 5;

unit-test/binding.gyp

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,23 @@
1111
},
1212
'targets': [
1313
{
14-
"target_name": "generateBindingCC",
15-
"type": "none",
16-
"actions": [ {
17-
"action_name": "generateBindingCC",
18-
"message": "Generating binding cc file",
19-
"outputs": ["generated/binding.cc"],
20-
"conditions": [
21-
[ "'true'=='true'", {
22-
"inputs": [""],
23-
"action": [
24-
"node",
25-
"generate-binding-cc.js",
14+
"target_name": "generateBindingCC",
15+
"type": "none",
16+
"actions": [ {
17+
"action_name": "generateBindingCC",
18+
"message": "Generating binding cc file",
19+
"outputs": ["generated/binding.cc"],
20+
"conditions": [
21+
[ "'true'=='true'", {
22+
"inputs": [""],
23+
"action": [
24+
"node",
25+
"generate-binding-cc.js",
2626
"<!@(node -p \"require('./injectTestParams').filesForBinding()\" )"
27-
]
28-
} ]
29-
]
30-
} ]
27+
]
28+
} ]
29+
]
30+
} ]
3131
},
3232
{
3333
'target_name': 'binding',
@@ -61,5 +61,12 @@
6161
'defines': ['NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS'],
6262
'dependencies': [ 'generateBindingCC' ]
6363
},
64+
{
65+
'target_name': 'binding_custom_namespace',
66+
'includes': ['../noexcept.gypi'],
67+
'sources': ['>@(build_sources)'],
68+
'defines': ['NAPI_CPP_CUSTOM_NAMESPACE=cstm'],
69+
'dependencies': [ 'generateBindingCC' ]
70+
},
6471
],
6572
}

0 commit comments

Comments
 (0)