diff --git a/src/node.cc b/src/node.cc index e6be00eeb3c185..2d0de0f28e6b31 100644 --- a/src/node.cc +++ b/src/node.cc @@ -124,6 +124,7 @@ #include #include #include +#include #include #include @@ -844,10 +845,15 @@ static ExitCode InitializeNodeWithArgsInternal( auto file_path = node::Dotenv::GetPathFromArgs(*argv); if (file_path.has_value()) { - auto cwd = Environment::GetCwd(Environment::GetExecPath(*argv)); - std::string path = cwd + kPathSeparator + file_path.value(); CHECK(!per_process::v8_initialized); - per_process::dotenv_file.ParsePath(path); + + if (file_path->is_absolute()) { + per_process::dotenv_file.ParsePath(file_path->string()); + } else { + auto cwd = Environment::GetCwd(Environment::GetExecPath(*argv)); + std::string path = cwd + kPathSeparator + file_path->string(); + per_process::dotenv_file.ParsePath(path); + } per_process::dotenv_file.AssignNodeOptionsIfAvailable(&node_options); } diff --git a/src/node_dotenv.cc b/src/node_dotenv.cc index d8d6fc1d55d3de..0f1db9db2737aa 100644 --- a/src/node_dotenv.cc +++ b/src/node_dotenv.cc @@ -8,7 +8,7 @@ namespace node { using v8::NewStringType; using v8::String; -std::optional Dotenv::GetPathFromArgs( +std::optional Dotenv::GetPathFromArgs( const std::vector& args) { std::string_view flag = "--env-file"; // Match the last `--env-file` @@ -26,7 +26,7 @@ std::optional Dotenv::GetPathFromArgs( auto equal_char = path->find('='); if (equal_char != std::string::npos) { - return path->substr(equal_char + 1); + return std::filesystem::path(path->substr(equal_char + 1)); } auto next_arg = std::prev(path); @@ -35,7 +35,7 @@ std::optional Dotenv::GetPathFromArgs( return std::nullopt; } - return *next_arg; + return std::filesystem::path(*next_arg); } void Dotenv::SetEnvironment(node::Environment* env) { diff --git a/src/node_dotenv.h b/src/node_dotenv.h index 2fb810386324fc..db40defdf3b09c 100644 --- a/src/node_dotenv.h +++ b/src/node_dotenv.h @@ -5,6 +5,7 @@ #include "util-inl.h" +#include #include #include @@ -23,7 +24,7 @@ class Dotenv { void AssignNodeOptionsIfAvailable(std::string* node_options); void SetEnvironment(Environment* env); - static std::optional GetPathFromArgs( + static std::optional GetPathFromArgs( const std::vector& args); private: diff --git a/test/parallel/test-dotenv-edge-cases.js b/test/parallel/test-dotenv-edge-cases.js index 1d256799bfbb13..a1cf7d4dc7a8a5 100644 --- a/test/parallel/test-dotenv-edge-cases.js +++ b/test/parallel/test-dotenv-edge-cases.js @@ -2,10 +2,12 @@ const common = require('../common'); const assert = require('node:assert'); +const path = require('node:path'); const { describe, it } = require('node:test'); const validEnvFilePath = '../fixtures/dotenv/valid.env'; const relativePath = '../fixtures/dotenv/node-options.env'; +const absolutePath = path.join(__dirname, relativePath); describe('.env supports edge cases', () => { @@ -35,4 +37,17 @@ describe('.env supports edge cases', () => { assert.strictEqual(child.code, 0); }); + it('should support absolute paths', async () => { + const code = ` + require('assert').strictEqual(process.env.CUSTOM_VARIABLE, 'hello-world'); + `.trim(); + const child = await common.spawnPromisified( + process.execPath, + [ `--env-file=${absolutePath}`, '--eval', code ], + { cwd: __dirname }, + ); + assert.strictEqual(child.stderr, ''); + assert.strictEqual(child.code, 0); + }); + });