| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 4cdb032 commit 816d37a
19 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2572,6 +2572,45 @@ added: v0.8.0 | |||
| 2572 | 2572 | ||
| 2573 | 2573 | Print stack traces for deprecations. | |
| 2574 | 2574 | ||
| 2575 | + ### `--trace-env` | ||
| 2576 | + | ||
| 2577 | + <!-- YAML | ||
| 2578 | + added: REPLACEME | ||
| 2579 | + --> | ||
| 2580 | + | ||
| 2581 | + Print information about any access to environment variables done in the current Node.js | ||
| 2582 | + instance to stderr, including: | ||
| 2583 | + | ||
| 2584 | + * The environment variable reads that Node.js does internally. | ||
| 2585 | + * Writes in the form of `process.env.KEY = "SOME VALUE"`. | ||
| 2586 | + * Reads in the form of `process.env.KEY`. | ||
| 2587 | + * Definitions in the form of `Object.defineProperty(process.env, 'KEY', {...})`. | ||
| 2588 | + * Queries in the form of `Object.hasOwn(process.env, 'KEY')`, | ||
| 2589 | + `process.env.hasOwnProperty('KEY')` or `'KEY' in process.env`. | ||
| 2590 | + * Deletions in the form of `delete process.env.KEY`. | ||
| 2591 | + * Enumerations inf the form of `...process.env` or `Object.keys(process.env)`. | ||
| 2592 | + | ||
| 2593 | + Only the names of the environment variables being accessed are printed. The values are not printed. | ||
| 2594 | + | ||
| 2595 | + To print the stack trace of the access, use `--trace-env-js-stack` and/or | ||
| 2596 | + `--trace-env-native-stack`. | ||
| 2597 | + | ||
| 2598 | + ### `--trace-env-js-stack` | ||
| 2599 | + | ||
| 2600 | + <!-- YAML | ||
| 2601 | + added: REPLACEME | ||
| 2602 | + --> | ||
| 2603 | + | ||
| 2604 | + In addition to what `--trace-env` does, this prints the JavaScript stack trace of the access. | ||
| 2605 | + | ||
| 2606 | + ### `--trace-env-native-stack` | ||
| 2607 | + | ||
| 2608 | + <!-- YAML | ||
| 2609 | + added: REPLACEME | ||
| 2610 | + --> | ||
| 2611 | + | ||
| 2612 | + In addition to what `--trace-env` does, this prints the native stack trace of the access. | ||
| 2613 | + | ||
| 2575 | 2614 | ### `--trace-event-categories` | |
| 2576 | 2615 | ||
| 2577 | 2616 | <!-- YAML | |
@@ -3118,6 +3157,9 @@ one is included in the list below. | |||
| 3118 | 3157 | * `--tls-min-v1.2` | |
| 3119 | 3158 | * `--tls-min-v1.3` | |
| 3120 | 3159 | * `--trace-deprecation` | |
| 3160 | + * `--trace-env-js-stack` | ||
| 3161 | + * `--trace-env-native-stack` | ||
| 3162 | + * `--trace-env` | ||
| 3121 | 3163 | * `--trace-event-categories` | |
| 3122 | 3164 | * `--trace-event-file-pattern` | |
| 3123 | 3165 | * `--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 | |
|---|---|---|---|
@@ -864,9 +864,6 @@ Environment::Environment(IsolateData* isolate_data, | |||
| 864 | 864 | EnvironmentFlags::kOwnsInspector; | |
| 865 | 865 | } | |
| 866 | 866 | ||
| 867 | - set_env_vars(per_process::system_environment); | ||
| 868 | - enabled_debug_list_.Parse(env_vars()); | ||
| 869 | - | ||
| 870 | 867 | // We create new copies of the per-Environment option sets, so that it is | |
| 871 | 868 | // easier to modify them after Environment creation. The defaults are | |
| 872 | 869 | // part of the per-Isolate option set, for which in turn the defaults are | |
@@ -876,6 +873,13 @@ Environment::Environment(IsolateData* isolate_data, | |||
| 876 | 873 | inspector_host_port_ = std::make_shared<ExclusiveAccess<HostPort>>( | |
| 877 | 874 | options_->debug_options().host_port); | |
| 878 | 875 | ||
| 876 | + set_env_vars(per_process::system_environment); | ||
| 877 | + // This should be done after options is created, so that --trace-env can be | ||
| 878 | + // checked when parsing NODE_DEBUG_NATIVE. It should also be done after | ||
| 879 | + // env_vars() is set so that the parser uses values from env->env_vars() | ||
| 880 | + // which may or may not be the system environment variable store. | ||
| 881 | + enabled_debug_list_.Parse(this); | ||
| 882 | + | ||
| 879 | 883 | heap_snapshot_near_heap_limit_ = | |
| 880 | 884 | static_cast<uint32_t>(options_->heap_snapshot_near_heap_limit); | |
| 881 | 885 | ||
@@ -1104,8 +1108,7 @@ void Environment::InitializeLibuv() { | |||
| 1104 | 1108 | ||
| 1105 | 1109 | void Environment::InitializeCompileCache() { | |
| 1106 | 1110 | std::string dir_from_env; | |
| 1107 | - if (!credentials::SafeGetenv( | ||
| 1108 | - "NODE_COMPILE_CACHE", &dir_from_env, env_vars()) || | ||
| 1111 | + if (!credentials::SafeGetenv("NODE_COMPILE_CACHE", &dir_from_env, this) || | ||
| 1109 | 1112 | dir_from_env.empty()) { | |
| 1110 | 1113 | return; | |
| 1111 | 1114 | } | |
@@ -1117,7 +1120,7 @@ CompileCacheEnableResult Environment::EnableCompileCache( | |||
| 1117 | 1120 | CompileCacheEnableResult result; | |
| 1118 | 1121 | std::string disable_env; | |
| 1119 | 1122 | if (credentials::SafeGetenv( | |
| 1120 | - "NODE_DISABLE_COMPILE_CACHE", &disable_env, env_vars())) { | ||
| 1123 | + "NODE_DISABLE_COMPILE_CACHE", &disable_env, this)) { | ||
| 1121 | 1124 | result.status = CompileCacheEnableStatus::DISABLED; | |
| 1122 | 1125 | result.message = "Disabled by NODE_DISABLE_COMPILE_CACHE"; | |
| 1123 | 1126 | Debug(this, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -993,7 +993,7 @@ InitializeOncePerProcessInternal(const std::vector<std::string>& args, | |||
| 993 | 993 | if (!(flags & ProcessInitializationFlags::kNoParseGlobalDebugVariables)) { | |
| 994 | 994 | // Initialized the enabled list for Debug() calls with system | |
| 995 | 995 | // environment variables. | |
| 996 | - per_process::enabled_debug_list.Parse(per_process::system_environment); | ||
| 996 | + per_process::enabled_debug_list.Parse(nullptr); | ||
| 997 | 997 | } | |
| 998 | 998 | ||
| 999 | 999 | 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 | |
|---|---|---|---|
@@ -759,6 +759,24 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { | |||
| 759 | 759 | "show stack traces on promise initialization and resolution", | |
| 760 | 760 | &EnvironmentOptions::trace_promises, | |
| 761 | 761 | kAllowedInEnvvar); | |
| 762 | + | ||
| 763 | + AddOption("--trace-env", | ||
| 764 | + "Print accesses to the environment variables", | ||
| 765 | + &EnvironmentOptions::trace_env, | ||
| 766 | + kAllowedInEnvvar); | ||
| 767 | + Implies("--trace-env-js-stack", "--trace-env"); | ||
| 768 | + Implies("--trace-env-native-stack", "--trace-env"); | ||
| 769 | + AddOption("--trace-env-js-stack", | ||
| 770 | + "Print accesses to the environment variables and the JavaScript " | ||
| 771 | + "stack trace", | ||
| 772 | + &EnvironmentOptions::trace_env_js_stack, | ||
| 773 | + kAllowedInEnvvar); | ||
| 774 | + AddOption( | ||
| 775 | + "--trace-env-native-stack", | ||
| 776 | + "Print accesses to the environment variables and the native stack trace", | ||
| 777 | + &EnvironmentOptions::trace_env_native_stack, | ||
| 778 | + kAllowedInEnvvar); | ||
| 779 | + | ||
| 762 | 780 | AddOption("--experimental-default-type", | |
| 763 | 781 | "set module system to use by default", | |
| 764 | 782 | &EnvironmentOptions::type, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -208,6 +208,9 @@ class EnvironmentOptions : public Options { | |||
| 208 | 208 | bool trace_uncaught = false; | |
| 209 | 209 | bool trace_warnings = false; | |
| 210 | 210 | bool trace_promises = false; | |
| 211 | + bool trace_env = false; | ||
| 212 | + bool trace_env_js_stack = false; | ||
| 213 | + bool trace_env_native_stack = false; | ||
| 211 | 214 | bool extra_info_on_fatal_exception = true; | |
| 212 | 215 | std::string unhandled_rejections; | |
| 213 | 216 | std::vector<std::string> userland_loaders; | |
| Back | FazBrowse Home | New Git URL |
0 commit comments