| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 646e057 commit 44fdf95
6 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -827,11 +827,13 @@ extern "C" NODE_EXTERN void node_module_register(void* mod); | |||
| 827 | 827 | #endif | |
| 828 | 828 | ||
| 829 | 829 | #if defined(_MSC_VER) | |
| 830 | - #pragma section(".CRT$XCU", read) | ||
| 831 | 830 | #define NODE_C_CTOR(fn) \ | |
| 832 | 831 | NODE_CTOR_PREFIX void __cdecl fn(void); \ | |
| 833 | - __declspec(dllexport, allocate(".CRT$XCU")) \ | ||
| 834 | - void (__cdecl*fn ## _)(void) = fn; \ | ||
| 832 | + namespace { \ | ||
| 833 | + struct fn##_ { \ | ||
| 834 | + fn##_() { fn(); }; \ | ||
| 835 | + } fn##_v_; \ | ||
| 836 | + } \ | ||
| 835 | 837 | NODE_CTOR_PREFIX void __cdecl fn(void) | |
| 836 | 838 | #else | |
| 837 | 839 | #define NODE_C_CTOR(fn) \ | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -44,12 +44,29 @@ typedef struct napi_module { | |||
| 44 | 44 | #define NAPI_MODULE_VERSION 1 | |
| 45 | 45 | ||
| 46 | 46 | #if defined(_MSC_VER) | |
| 47 | + #if defined(__cplusplus) | ||
| 48 | + #define NAPI_C_CTOR(fn) \ | ||
| 49 | + static void __cdecl fn(void); \ | ||
| 50 | + namespace { \ | ||
| 51 | + struct fn##_ { \ | ||
| 52 | + fn##_() { fn(); } \ | ||
| 53 | + } fn##_v_; \ | ||
| 54 | + } \ | ||
| 55 | + static void __cdecl fn(void) | ||
| 56 | + #else // !defined(__cplusplus) | ||
| 47 | 57 | #pragma section(".CRT$XCU", read) | |
| 58 | + // The NAPI_C_CTOR macro defines a function fn that is called during CRT | ||
| 59 | + // initialization. | ||
| 60 | + // C does not support dynamic initialization of static variables and this code | ||
| 61 | + // simulates C++ behavior. Exporting the function pointer prevents it from being | ||
| 62 | + // optimized. See for details: | ||
| 63 | + // https://docs.microsoft.com/en-us/cpp/c-runtime-library/crt-initialization?view=msvc-170 | ||
| 48 | 64 | #define NAPI_C_CTOR(fn) \ | |
| 49 | 65 | static void __cdecl fn(void); \ | |
| 50 | 66 | __declspec(dllexport, allocate(".CRT$XCU")) void(__cdecl * fn##_)(void) = \ | |
| 51 | 67 | fn; \ | |
| 52 | 68 | static void __cdecl fn(void) | |
| 69 | + #endif // defined(__cplusplus) | ||
| 53 | 70 | #else | |
| 54 | 71 | #define NAPI_C_CTOR(fn) \ | |
| 55 | 72 | static void fn(void) __attribute__((constructor)); \ | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -62,6 +62,9 @@ | |||
| 62 | 62 | #define DECLARE_NODE_API_GETTER(name, func) \ | |
| 63 | 63 | { (name), NULL, NULL, (func), NULL, NULL, napi_default, NULL } | |
| 64 | 64 | ||
| 65 | + #define DECLARE_NODE_API_PROPERTY_VALUE(name, value) \ | ||
| 66 | + { (name), NULL, NULL, NULL, NULL, (value), napi_default, NULL } | ||
| 67 | + | ||
| 65 | 68 | void add_returned_status(napi_env env, | |
| 66 | 69 | const char* key, | |
| 67 | 70 | napi_value object, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,8 @@ | |||
| 1 | + { | ||
| 2 | + "targets": [ | ||
| 3 | + { | ||
| 4 | + "target_name": "test_init_order", | ||
| 5 | + "sources": [ "test_init_order.cc" ] | ||
| 6 | + } | ||
| 7 | + ] | ||
| 8 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,10 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + | ||
| 3 | + // This test verifies that C++ static variable dynamic initialization is called | ||
| 4 | + // correctly and does not interfere with the module initialization. | ||
| 5 | + const common = require('../../common'); | ||
| 6 | + const test_init_order = require(`./build/${common.buildType}/test_init_order`); | ||
| 7 | + const assert = require('assert'); | ||
| 8 | + | ||
| 9 | + assert.strictEqual(test_init_order.cppIntValue, 42); | ||
| 10 | + assert.strictEqual(test_init_order.cppStringValue, '123'); | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,52 @@ | |||
| 1 | + #include <node_api.h> | ||
| 2 | + #include <memory> | ||
| 3 | + #include <string> | ||
| 4 | + #include "../../js-native-api/common.h" | ||
| 5 | + | ||
| 6 | + // This test verifies that use of the NAPI_MODULE in C++ code does not | ||
| 7 | + // interfere with the C++ dynamic static initializers. | ||
| 8 | + | ||
| 9 | + namespace { | ||
| 10 | + | ||
| 11 | + // This class uses dynamic static initializers for the test. | ||
| 12 | + // In production code developers must avoid dynamic static initializers because | ||
| 13 | + // they affect the start up time. They must prefer static initialization such as | ||
| 14 | + // use of constexpr functions or classes with constexpr constructors. E.g. | ||
| 15 | + // instead of using std::string, it is preferrable to use const char[], or | ||
| 16 | + // constexpr std::string_view starting with C++17, or even constexpr | ||
| 17 | + // std::string starting with C++20. | ||
| 18 | + struct MyClass { | ||
| 19 | + static const std::unique_ptr<int> valueHolder; | ||
| 20 | + static const std::string testString; | ||
| 21 | + }; | ||
| 22 | + | ||
| 23 | + const std::unique_ptr<int> MyClass::valueHolder = | ||
| 24 | + std::unique_ptr<int>(new int(42)); | ||
| 25 | + // NOLINTNEXTLINE(runtime/string) | ||
| 26 | + const std::string MyClass::testString = std::string("123"); | ||
| 27 | + | ||
| 28 | + } // namespace | ||
| 29 | + | ||
| 30 | + EXTERN_C_START | ||
| 31 | + napi_value Init(napi_env env, napi_value exports) { | ||
| 32 | + napi_value cppIntValue, cppStringValue; | ||
| 33 | + NODE_API_CALL(env, | ||
| 34 | + napi_create_int32(env, *MyClass::valueHolder, &cppIntValue)); | ||
| 35 | + NODE_API_CALL( | ||
| 36 | + env, | ||
| 37 | + napi_create_string_utf8( | ||
| 38 | + env, MyClass::testString.c_str(), NAPI_AUTO_LENGTH, &cppStringValue)); | ||
| 39 | + | ||
| 40 | + napi_property_descriptor descriptors[] = { | ||
| 41 | + DECLARE_NODE_API_PROPERTY_VALUE("cppIntValue", cppIntValue), | ||
| 42 | + DECLARE_NODE_API_PROPERTY_VALUE("cppStringValue", cppStringValue)}; | ||
| 43 | + | ||
| 44 | + NODE_API_CALL(env, | ||
| 45 | + napi_define_properties( | ||
| 46 | + env, exports, std::size(descriptors), descriptors)); | ||
| 47 | + | ||
| 48 | + return exports; | ||
| 49 | + } | ||
| 50 | + EXTERN_C_END | ||
| 51 | + | ||
| 52 | + NAPI_MODULE(NODE_GYP_MODULE_NAME, Init) | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments