Skip to content

Commit 9121453

Browse files
committed
src: parse dotenv with the rest of the options
1 parent 75e4d0d commit 9121453

File tree

5 files changed

+61
-62
lines changed

5 files changed

+61
-62
lines changed

src/node.cc

+28-22
Original file line numberDiff line numberDiff line change
@@ -851,28 +851,6 @@ static ExitCode InitializeNodeWithArgsInternal(
851851
HandleEnvOptions(per_process::cli_options->per_isolate->per_env);
852852

853853
std::string node_options;
854-
auto file_paths = node::Dotenv::GetPathFromArgs(*argv);
855-
856-
if (!file_paths.empty()) {
857-
CHECK(!per_process::v8_initialized);
858-
859-
for (const auto& file_path : file_paths) {
860-
switch (per_process::dotenv_file.ParsePath(file_path)) {
861-
case Dotenv::ParseResult::Valid:
862-
break;
863-
case Dotenv::ParseResult::InvalidContent:
864-
errors->push_back(file_path + ": invalid format");
865-
break;
866-
case Dotenv::ParseResult::FileError:
867-
errors->push_back(file_path + ": not found");
868-
break;
869-
default:
870-
UNREACHABLE();
871-
}
872-
}
873-
874-
per_process::dotenv_file.AssignNodeOptionsIfAvailable(&node_options);
875-
}
876854

877855
#if !defined(NODE_WITHOUT_NODE_OPTIONS)
878856
if (!(flags & ProcessInitializationFlags::kDisableNodeOptionsEnv)) {
@@ -909,6 +887,34 @@ static ExitCode InitializeNodeWithArgsInternal(
909887
if (exit_code != ExitCode::kNoFailure) return exit_code;
910888
}
911889

890+
if (!per_process::cli_options->per_isolate->per_env->env_file.empty()) {
891+
CHECK(!per_process::v8_initialized);
892+
893+
for (const auto& file_path :
894+
per_process::cli_options->per_isolate->per_env->env_file) {
895+
switch (per_process::dotenv_file.ParsePath(file_path)) {
896+
case Dotenv::ParseResult::Valid:
897+
break;
898+
case Dotenv::ParseResult::InvalidContent:
899+
errors->push_back(file_path + ": invalid format");
900+
break;
901+
case Dotenv::ParseResult::FileError:
902+
errors->push_back(file_path + ": not found");
903+
break;
904+
default:
905+
UNREACHABLE();
906+
}
907+
}
908+
909+
std::vector<std::string> env_argv = ParseNodeOptionsEnvVar(
910+
per_process::dotenv_file.GetNodeOptions(), errors);
911+
env_argv.insert(env_argv.begin(), argv->at(0));
912+
913+
const ExitCode exit_code =
914+
ProcessGlobalArgsInternal(&env_argv, nullptr, errors, kAllowedInEnvvar);
915+
if (exit_code != ExitCode::kNoFailure) return exit_code;
916+
}
917+
912918
// Set the process.title immediately after processing argv if --title is set.
913919
if (!per_process::cli_options->title.empty())
914920
uv_set_process_title(per_process::cli_options->title.c_str());

src/node_dotenv.cc

+3-38
Original file line numberDiff line numberDiff line change
@@ -11,38 +11,6 @@ using v8::NewStringType;
1111
using v8::Object;
1212
using v8::String;
1313

14-
std::vector<std::string> Dotenv::GetPathFromArgs(
15-
const std::vector<std::string>& args) {
16-
const auto find_match = [](const std::string& arg) {
17-
return arg == "--" || arg == "--env-file" || arg.starts_with("--env-file=");
18-
};
19-
std::vector<std::string> paths;
20-
auto path = std::find_if(args.begin(), args.end(), find_match);
21-
22-
while (path != args.end()) {
23-
if (*path == "--") {
24-
return paths;
25-
}
26-
auto equal_char = path->find('=');
27-
28-
if (equal_char != std::string::npos) {
29-
paths.push_back(path->substr(equal_char + 1));
30-
} else {
31-
auto next_path = std::next(path);
32-
33-
if (next_path == args.end()) {
34-
return paths;
35-
}
36-
37-
paths.push_back(*next_path);
38-
}
39-
40-
path = std::find_if(++path, args.end(), find_match);
41-
}
42-
43-
return paths;
44-
}
45-
4614
void Dotenv::SetEnvironment(node::Environment* env) {
4715
auto isolate = env->isolate();
4816

@@ -261,12 +229,9 @@ Dotenv::ParseResult Dotenv::ParsePath(const std::string_view path) {
261229
return ParseResult::Valid;
262230
}
263231

264-
void Dotenv::AssignNodeOptionsIfAvailable(std::string* node_options) const {
265-
auto match = store_.find("NODE_OPTIONS");
266-
267-
if (match != store_.end()) {
268-
*node_options = match->second;
269-
}
232+
std::string Dotenv::GetNodeOptions() const {
233+
auto it = store_.find("NODE_OPTIONS");
234+
return (it != store_.end()) ? it->second : "";
270235
}
271236

272237
} // namespace node

src/node_dotenv.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class Dotenv {
2323

2424
void ParseContent(const std::string_view content);
2525
ParseResult ParsePath(const std::string_view path);
26-
void AssignNodeOptionsIfAvailable(std::string* node_options) const;
26+
std::string GetNodeOptions() const;
2727
void SetEnvironment(Environment* env);
2828
v8::Local<v8::Object> ToObject(Environment* env) const;
2929

src/node_options.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ class EnvironmentOptions : public Options {
176176
#endif // HAVE_INSPECTOR
177177
std::string redirect_warnings;
178178
std::string diagnostic_dir;
179-
std::string env_file;
179+
std::vector<std::string> env_file;
180180
bool has_env_file_string = false;
181181
bool test_runner = false;
182182
uint64_t test_runner_concurrency = 0;

test/parallel/test-dotenv-edge-cases.js

+28
Original file line numberDiff line numberDiff line change
@@ -113,3 +113,31 @@ describe('.env supports edge cases', () => {
113113
assert.strictEqual(child.code, 0);
114114
});
115115
});
116+
117+
// Ref: https://github.com/nodejs/node/pull/54913
118+
it('CLI edge cases', async () => {
119+
const edgeCases = [
120+
{
121+
flags: [fixtures.path('empty.js'), '--env-file=nonexistent.env'],
122+
},
123+
{
124+
flags: ['--eval=""', '--', '--env-file=nonexistent.env'],
125+
},
126+
{
127+
flags: ['--invalid-argument', '--env-file=nonexistent.env'],
128+
error: 'bad option: --invalid-argument',
129+
},
130+
{
131+
flags: ['--env-file-ABCD=nonexistent.env'],
132+
error: 'bad option: --env-file-ABCD=nonexistent.env'
133+
},
134+
];
135+
for (const { flags, error } of edgeCases) {
136+
const child = await common.spawnPromisified(process.execPath, flags);
137+
if (error) {
138+
assert.notStrictEqual(child.code, 0);
139+
// Remove the leading '<path>: '
140+
assert.strictEqual(child.stderr.substring(process.execPath.length + 2).trim(), error);
141+
}
142+
}
143+
});

0 commit comments

Comments
 (0)