| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent ea48918 commit a933103
19 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2604,6 +2604,45 @@ added: v0.8.0 | |||
| 2604 | 2604 | ||
| 2605 | 2605 | Print stack traces for deprecations. | |
| 2606 | 2606 | ||
| 2607 | + ### `--trace-env` | ||
| 2608 | + | ||
| 2609 | + <!-- YAML | ||
| 2610 | + added: REPLACEME | ||
| 2611 | + --> | ||
| 2612 | + | ||
| 2613 | + Print information about any access to environment variables done in the current Node.js | ||
| 2614 | + instance to stderr, including: | ||
| 2615 | + | ||
| 2616 | + * The environment variable reads that Node.js does internally. | ||
| 2617 | + * Writes in the form of `process.env.KEY = "SOME VALUE"`. | ||
| 2618 | + * Reads in the form of `process.env.KEY`. | ||
| 2619 | + * Definitions in the form of `Object.defineProperty(process.env, 'KEY', {...})`. | ||
| 2620 | + * Queries in the form of `Object.hasOwn(process.env, 'KEY')`, | ||
| 2621 | + `process.env.hasOwnProperty('KEY')` or `'KEY' in process.env`. | ||
| 2622 | + * Deletions in the form of `delete process.env.KEY`. | ||
| 2623 | + * Enumerations inf the form of `...process.env` or `Object.keys(process.env)`. | ||
| 2624 | + | ||
| 2625 | + Only the names of the environment variables being accessed are printed. The values are not printed. | ||
| 2626 | + | ||
| 2627 | + To print the stack trace of the access, use `--trace-env-js-stack` and/or | ||
| 2628 | + `--trace-env-native-stack`. | ||
| 2629 | + | ||
| 2630 | + ### `--trace-env-js-stack` | ||
| 2631 | + | ||
| 2632 | + <!-- YAML | ||
| 2633 | + added: REPLACEME | ||
| 2634 | + --> | ||
| 2635 | + | ||
| 2636 | + In addition to what `--trace-env` does, this prints the JavaScript stack trace of the access. | ||
| 2637 | + | ||
| 2638 | + ### `--trace-env-native-stack` | ||
| 2639 | + | ||
| 2640 | + <!-- YAML | ||
| 2641 | + added: REPLACEME | ||
| 2642 | + --> | ||
| 2643 | + | ||
| 2644 | + In addition to what `--trace-env` does, this prints the native stack trace of the access. | ||
| 2645 | + | ||
| 2607 | 2646 | ### `--trace-event-categories` | |
| 2608 | 2647 | ||
| 2609 | 2648 | <!-- YAML | |
@@ -3150,6 +3189,9 @@ one is included in the list below. | |||
| 3150 | 3189 | * `--tls-min-v1.3` | |
| 3151 | 3190 | * `--trace-atomics-wait` | |
| 3152 | 3191 | * `--trace-deprecation` | |
| 3192 | + * `--trace-env-js-stack` | ||
| 3193 | + * `--trace-env-native-stack` | ||
| 3194 | + * `--trace-env` | ||
| 3153 | 3195 | * `--trace-event-categories` | |
| 3154 | 3196 | * `--trace-event-file-pattern` | |
| 3155 | 3197 | * `--trace-events-enabled` | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -62,9 +62,9 @@ EnabledDebugList enabled_debug_list; | |||
| 62 | 62 | using v8::Local; | |
| 63 | 63 | using v8::StackTrace; | |
| 64 | 64 | ||
| 65 | - void EnabledDebugList::Parse(std::shared_ptr<KVStore> env_vars) { | ||
| 65 | + void EnabledDebugList::Parse(Environment* env) { | ||
| 66 | 66 | std::string cats; | |
| 67 | - credentials::SafeGetenv("NODE_DEBUG_NATIVE", &cats, env_vars); | ||
| 67 | + credentials::SafeGetenv("NODE_DEBUG_NATIVE", &cats, env); | ||
| 68 | 68 | Parse(cats); | |
| 69 | 69 | } | |
| 70 | 70 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -74,10 +74,10 @@ class NODE_EXTERN_PRIVATE EnabledDebugList { | |||
| 74 | 74 | return enabled_[static_cast<unsigned int>(category)]; | |
| 75 | 75 | } | |
| 76 | 76 | ||
| 77 | - // Uses NODE_DEBUG_NATIVE to initialize the categories. The env_vars variable | ||
| 77 | + // Uses NODE_DEBUG_NATIVE to initialize the categories. env->env_vars() | ||
| 78 | 78 | // is parsed if it is not a nullptr, otherwise the system environment | |
| 79 | 79 | // variables are parsed. | |
| 80 | - void Parse(std::shared_ptr<KVStore> env_vars); | ||
| 80 | + void Parse(Environment* env); | ||
| 81 | 81 | ||
| 82 | 82 | private: | |
| 83 | 83 | // Enable all categories matching cats. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -875,9 +875,6 @@ Environment::Environment(IsolateData* isolate_data, | |||
| 875 | 875 | EnvironmentFlags::kOwnsInspector; | |
| 876 | 876 | } | |
| 877 | 877 | ||
| 878 | - set_env_vars(per_process::system_environment); | ||
| 879 | - enabled_debug_list_.Parse(env_vars()); | ||
| 880 | - | ||
| 881 | 878 | // We create new copies of the per-Environment option sets, so that it is | |
| 882 | 879 | // easier to modify them after Environment creation. The defaults are | |
| 883 | 880 | // part of the per-Isolate option set, for which in turn the defaults are | |
@@ -887,6 +884,13 @@ Environment::Environment(IsolateData* isolate_data, | |||
| 887 | 884 | inspector_host_port_ = std::make_shared<ExclusiveAccess<HostPort>>( | |
| 888 | 885 | options_->debug_options().host_port); | |
| 889 | 886 | ||
| 887 | + set_env_vars(per_process::system_environment); | ||
| 888 | + // This should be done after options is created, so that --trace-env can be | ||
| 889 | + // checked when parsing NODE_DEBUG_NATIVE. It should also be done after | ||
| 890 | + // env_vars() is set so that the parser uses values from env->env_vars() | ||
| 891 | + // which may or may not be the system environment variable store. | ||
| 892 | + enabled_debug_list_.Parse(this); | ||
| 893 | + | ||
| 890 | 894 | heap_snapshot_near_heap_limit_ = | |
| 891 | 895 | static_cast<uint32_t>(options_->heap_snapshot_near_heap_limit); | |
| 892 | 896 | ||
@@ -1115,8 +1119,7 @@ void Environment::InitializeLibuv() { | |||
| 1115 | 1119 | ||
| 1116 | 1120 | void Environment::InitializeCompileCache() { | |
| 1117 | 1121 | std::string dir_from_env; | |
| 1118 | - if (!credentials::SafeGetenv( | ||
| 1119 | - "NODE_COMPILE_CACHE", &dir_from_env, env_vars()) || | ||
| 1122 | + if (!credentials::SafeGetenv("NODE_COMPILE_CACHE", &dir_from_env, this) || | ||
| 1120 | 1123 | dir_from_env.empty()) { | |
| 1121 | 1124 | return; | |
| 1122 | 1125 | } | |
@@ -1128,7 +1131,7 @@ CompileCacheEnableResult Environment::EnableCompileCache( | |||
| 1128 | 1131 | CompileCacheEnableResult result; | |
| 1129 | 1132 | std::string disable_env; | |
| 1130 | 1133 | if (credentials::SafeGetenv( | |
| 1131 | - "NODE_DISABLE_COMPILE_CACHE", &disable_env, env_vars())) { | ||
| 1134 | + "NODE_DISABLE_COMPILE_CACHE", &disable_env, this)) { | ||
| 1132 | 1135 | result.status = CompileCacheEnableStatus::DISABLED; | |
| 1133 | 1136 | result.message = "Disabled by NODE_DISABLE_COMPILE_CACHE"; | |
| 1134 | 1137 | Debug(this, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1045,7 +1045,7 @@ InitializeOncePerProcessInternal(const std::vector<std::string>& args, | |||
| 1045 | 1045 | if (!(flags & ProcessInitializationFlags::kNoParseGlobalDebugVariables)) { | |
| 1046 | 1046 | // Initialized the enabled list for Debug() calls with system | |
| 1047 | 1047 | // environment variables. | |
| 1048 | - per_process::enabled_debug_list.Parse(per_process::system_environment); | ||
| 1048 | + per_process::enabled_debug_list.Parse(nullptr); | ||
| 1049 | 1049 | } | |
| 1050 | 1050 | ||
| 1051 | 1051 | PlatformInit(flags); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -72,9 +72,7 @@ static bool HasOnly(int capability) { | |||
| 72 | 72 | // process only has the capability CAP_NET_BIND_SERVICE set. If the current | |
| 73 | 73 | // process does not have any capabilities set and the process is running as | |
| 74 | 74 | // setuid root then lookup will not be allowed. | |
| 75 | - bool SafeGetenv(const char* key, | ||
| 76 | - std::string* text, | ||
| 77 | - std::shared_ptr<KVStore> env_vars) { | ||
| 75 | + bool SafeGetenv(const char* key, std::string* text, Environment* env) { | ||
| 78 | 76 | #if !defined(__CloudABI__) && !defined(_WIN32) | |
| 79 | 77 | #if defined(__linux__) | |
| 80 | 78 | if ((!HasOnly(CAP_NET_BIND_SERVICE) && linux_at_secure()) || | |
@@ -87,14 +85,31 @@ bool SafeGetenv(const char* key, | |||
| 87 | 85 | ||
| 88 | 86 | // Fallback to system environment which reads the real environment variable | |
| 89 | 87 | // through uv_os_getenv. | |
| 90 | - if (env_vars == nullptr) { | ||
| 88 | + std::shared_ptr<KVStore> env_vars; | ||
| 89 | + if (env == nullptr) { | ||
| 91 | 90 | env_vars = per_process::system_environment; | |
| 91 | + } else { | ||
| 92 | + env_vars = env->env_vars(); | ||
| 92 | 93 | } | |
| 93 | 94 | ||
| 94 | 95 | std::optional<std::string> value = env_vars->Get(key); | |
| 95 | - if (!value.has_value()) return false; | ||
| 96 | - *text = value.value(); | ||
| 97 | - return true; | ||
| 96 | + | ||
| 97 | + bool has_env = value.has_value(); | ||
| 98 | + if (has_env) { | ||
| 99 | + *text = value.value(); | ||
| 100 | + } | ||
| 101 | + | ||
| 102 | + auto options = | ||
| 103 | + (env != nullptr ? env->options() | ||
| 104 | + : per_process::cli_options->per_isolate->per_env); | ||
| 105 | + | ||
| 106 | + if (options->trace_env) { | ||
| 107 | + fprintf(stderr, "[--trace-env] get environment variable \"%s\"\n", key); | ||
| 108 | + | ||
| 109 | + PrintTraceEnvStack(options); | ||
| 110 | + } | ||
| 111 | + | ||
| 112 | + return has_env; | ||
| 98 | 113 | } | |
| 99 | 114 | ||
| 100 | 115 | static void SafeGetenv(const FunctionCallbackInfo<Value>& args) { | |
@@ -103,7 +118,7 @@ static void SafeGetenv(const FunctionCallbackInfo<Value>& args) { | |||
| 103 | 118 | Isolate* isolate = env->isolate(); | |
| 104 | 119 | Utf8Value strenvtag(isolate, args[0]); | |
| 105 | 120 | std::string text; | |
| 106 | - if (!SafeGetenv(*strenvtag, &text, env->env_vars())) return; | ||
| 121 | + if (!SafeGetenv(*strenvtag, &text, env)) return; | ||
| 107 | 122 | Local<Value> result = | |
| 108 | 123 | ToV8Value(isolate->GetCurrentContext(), text).ToLocalChecked(); | |
| 109 | 124 | args.GetReturnValue().Set(result); | |
@@ -117,7 +132,7 @@ static void GetTempDir(const FunctionCallbackInfo<Value>& args) { | |||
| 117 | 132 | ||
| 118 | 133 | // Let's wrap SafeGetEnv since it returns true for empty string. | |
| 119 | 134 | auto get_env = [&dir, &env](std::string_view key) { | |
| 120 | - USE(SafeGetenv(key.data(), &dir, env->env_vars())); | ||
| 135 | + USE(SafeGetenv(key.data(), &dir, env)); | ||
| 121 | 136 | return !dir.empty(); | |
| 122 | 137 | }; | |
| 123 | 138 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -337,6 +337,19 @@ Maybe<void> KVStore::AssignToObject(v8::Isolate* isolate, | |||
| 337 | 337 | return JustVoid(); | |
| 338 | 338 | } | |
| 339 | 339 | ||
| 340 | + void PrintTraceEnvStack(Environment* env) { | ||
| 341 | + PrintTraceEnvStack(env->options()); | ||
| 342 | + } | ||
| 343 | + | ||
| 344 | + void PrintTraceEnvStack(std::shared_ptr<EnvironmentOptions> options) { | ||
| 345 | + if (options->trace_env_native_stack) { | ||
| 346 | + DumpNativeBacktrace(stderr); | ||
| 347 | + } | ||
| 348 | + if (options->trace_env_js_stack) { | ||
| 349 | + DumpJavaScriptBacktrace(stderr); | ||
| 350 | + } | ||
| 351 | + } | ||
| 352 | + | ||
| 340 | 353 | static Intercepted EnvGetter(Local<Name> property, | |
| 341 | 354 | const PropertyCallbackInfo<Value>& info) { | |
| 342 | 355 | Environment* env = Environment::GetCurrent(info); | |
@@ -348,7 +361,18 @@ static Intercepted EnvGetter(Local<Name> property, | |||
| 348 | 361 | CHECK(property->IsString()); | |
| 349 | 362 | MaybeLocal<String> value_string = | |
| 350 | 363 | env->env_vars()->Get(env->isolate(), property.As<String>()); | |
| 351 | - if (!value_string.IsEmpty()) { | ||
| 364 | + | ||
| 365 | + bool has_env = !value_string.IsEmpty(); | ||
| 366 | + if (env->options()->trace_env) { | ||
| 367 | + Utf8Value key(env->isolate(), property.As<String>()); | ||
| 368 | + fprintf(stderr, | ||
| 369 | + "[--trace-env] get environment variable \"%.*s\"\n", | ||
| 370 | + static_cast<int>(key.length()), | ||
| 371 | + key.out()); | ||
| 372 | + PrintTraceEnvStack(env); | ||
| 373 | + } | ||
| 374 | + | ||
| 375 | + if (has_env) { | ||
| 352 | 376 | info.GetReturnValue().Set(value_string.ToLocalChecked()); | |
| 353 | 377 | return Intercepted::kYes; | |
| 354 | 378 | } | |
@@ -386,6 +410,14 @@ static Intercepted EnvSetter(Local<Name> property, | |||
| 386 | 410 | } | |
| 387 | 411 | ||
| 388 | 412 | env->env_vars()->Set(env->isolate(), key, value_string); | |
| 413 | + if (env->options()->trace_env) { | ||
| 414 | + Utf8Value key_utf8(env->isolate(), key); | ||
| 415 | + fprintf(stderr, | ||
| 416 | + "[--trace-env] set environment variable \"%.*s\"\n", | ||
| 417 | + static_cast<int>(key_utf8.length()), | ||
| 418 | + key_utf8.out()); | ||
| 419 | + PrintTraceEnvStack(env); | ||
| 420 | + } | ||
| 389 | 421 | ||
| 390 | 422 | return Intercepted::kYes; | |
| 391 | 423 | } | |
@@ -396,7 +428,18 @@ static Intercepted EnvQuery(Local<Name> property, | |||
| 396 | 428 | CHECK(env->has_run_bootstrapping_code()); | |
| 397 | 429 | if (property->IsString()) { | |
| 398 | 430 | int32_t rc = env->env_vars()->Query(env->isolate(), property.As<String>()); | |
| 399 | - if (rc != -1) { | ||
| 431 | + bool has_env = (rc != -1); | ||
| 432 | + | ||
| 433 | + if (env->options()->trace_env) { | ||
| 434 | + Utf8Value key_utf8(env->isolate(), property.As<String>()); | ||
| 435 | + fprintf(stderr, | ||
| 436 | + "[--trace-env] query environment variable \"%.*s\": %s\n", | ||
| 437 | + static_cast<int>(key_utf8.length()), | ||
| 438 | + key_utf8.out(), | ||
| 439 | + has_env ? "is set" : "is not set"); | ||
| 440 | + PrintTraceEnvStack(env); | ||
| 441 | + } | ||
| 442 | + if (has_env) { | ||
| 400 | 443 | // Return attributes for the property. | |
| 401 | 444 | info.GetReturnValue().Set(v8::None); | |
| 402 | 445 | return Intercepted::kYes; | |
@@ -411,6 +454,15 @@ static Intercepted EnvDeleter(Local<Name> property, | |||
| 411 | 454 | CHECK(env->has_run_bootstrapping_code()); | |
| 412 | 455 | if (property->IsString()) { | |
| 413 | 456 | env->env_vars()->Delete(env->isolate(), property.As<String>()); | |
| 457 | + | ||
| 458 | + if (env->options()->trace_env) { | ||
| 459 | + Utf8Value key_utf8(env->isolate(), property.As<String>()); | ||
| 460 | + fprintf(stderr, | ||
| 461 | + "[--trace-env] delete environment variable \"%.*s\"\n", | ||
| 462 | + static_cast<int>(key_utf8.length()), | ||
| 463 | + key_utf8.out()); | ||
| 464 | + PrintTraceEnvStack(env); | ||
| 465 | + } | ||
| 414 | 466 | } | |
| 415 | 467 | ||
| 416 | 468 | // process.env never has non-configurable properties, so always | |
@@ -423,6 +475,12 @@ static void EnvEnumerator(const PropertyCallbackInfo<Array>& info) { | |||
| 423 | 475 | Environment* env = Environment::GetCurrent(info); | |
| 424 | 476 | CHECK(env->has_run_bootstrapping_code()); | |
| 425 | 477 | ||
| 478 | + if (env->options()->trace_env) { | ||
| 479 | + fprintf(stderr, "[--trace-env] enumerate environment variables\n"); | ||
| 480 | + | ||
| 481 | + PrintTraceEnvStack(env); | ||
| 482 | + } | ||
| 483 | + | ||
| 426 | 484 | info.GetReturnValue().Set( | |
| 427 | 485 | env->env_vars()->Enumerate(env->isolate())); | |
| 428 | 486 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -321,11 +321,12 @@ class ThreadPoolWork { | |||
| 321 | 321 | #endif // defined(__POSIX__) && !defined(__ANDROID__) && !defined(__CloudABI__) | |
| 322 | 322 | ||
| 323 | 323 | namespace credentials { | |
| 324 | - bool SafeGetenv(const char* key, | ||
| 325 | - std::string* text, | ||
| 326 | - std::shared_ptr<KVStore> env_vars = nullptr); | ||
| 324 | + bool SafeGetenv(const char* key, std::string* text, Environment* env = nullptr); | ||
| 327 | 325 | } // namespace credentials | |
| 328 | 326 | ||
| 327 | + void PrintTraceEnvStack(Environment* env); | ||
| 328 | + void PrintTraceEnvStack(std::shared_ptr<EnvironmentOptions> options); | ||
| 329 | + | ||
| 329 | 330 | void DefineZlibConstants(v8::Local<v8::Object> target); | |
| 330 | 331 | v8::Isolate* NewIsolate(v8::Isolate::CreateParams* params, | |
| 331 | 332 | uv_loop_t* event_loop, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -775,6 +775,24 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { | |||
| 775 | 775 | "show stack traces on promise initialization and resolution", | |
| 776 | 776 | &EnvironmentOptions::trace_promises, | |
| 777 | 777 | kAllowedInEnvvar); | |
| 778 | + | ||
| 779 | + AddOption("--trace-env", | ||
| 780 | + "Print accesses to the environment variables", | ||
| 781 | + &EnvironmentOptions::trace_env, | ||
| 782 | + kAllowedInEnvvar); | ||
| 783 | + Implies("--trace-env-js-stack", "--trace-env"); | ||
| 784 | + Implies("--trace-env-native-stack", "--trace-env"); | ||
| 785 | + AddOption("--trace-env-js-stack", | ||
| 786 | + "Print accesses to the environment variables and the JavaScript " | ||
| 787 | + "stack trace", | ||
| 788 | + &EnvironmentOptions::trace_env_js_stack, | ||
| 789 | + kAllowedInEnvvar); | ||
| 790 | + AddOption( | ||
| 791 | + "--trace-env-native-stack", | ||
| 792 | + "Print accesses to the environment variables and the native stack trace", | ||
| 793 | + &EnvironmentOptions::trace_env_native_stack, | ||
| 794 | + kAllowedInEnvvar); | ||
| 795 | + | ||
| 778 | 796 | AddOption("--experimental-default-type", | |
| 779 | 797 | "set module system to use by default", | |
| 780 | 798 | &EnvironmentOptions::type, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -210,6 +210,9 @@ class EnvironmentOptions : public Options { | |||
| 210 | 210 | bool trace_uncaught = false; | |
| 211 | 211 | bool trace_warnings = false; | |
| 212 | 212 | bool trace_promises = false; | |
| 213 | + bool trace_env = false; | ||
| 214 | + bool trace_env_js_stack = false; | ||
| 215 | + bool trace_env_native_stack = false; | ||
| 213 | 216 | bool extra_info_on_fatal_exception = true; | |
| 214 | 217 | std::string unhandled_rejections; | |
| 215 | 218 | std::vector<std::string> userland_loaders; | |
| Back | FazBrowse Home | New Git URL |
0 commit comments