7
7
#include " node_errors.h"
8
8
#include " node_external_reference.h"
9
9
#include " node_internals.h"
10
+ #include " node_options.h"
10
11
#include " node_snapshot_builder.h"
11
12
#include " node_union_bytes.h"
12
13
#include " node_v8_platform-inl.h"
@@ -86,6 +87,11 @@ size_t SeaSerializer::Write(const SeaResource& sea) {
86
87
uint32_t flags = static_cast <uint32_t >(sea.flags );
87
88
Debug (" Write SEA flags %x\n " , flags);
88
89
written_total += WriteArithmetic<uint32_t >(flags);
90
+
91
+ Debug (" Write SEA resource exec argv extension %u\n " ,
92
+ static_cast <uint8_t >(sea.exec_argv_extension ));
93
+ written_total +=
94
+ WriteArithmetic<uint8_t >(static_cast <uint8_t >(sea.exec_argv_extension ));
89
95
DCHECK_EQ (written_total, SeaResource::kHeaderSize );
90
96
91
97
Debug (" Write SEA code path %p, size=%zu\n " ,
@@ -158,6 +164,11 @@ SeaResource SeaDeserializer::Read() {
158
164
CHECK_EQ (magic, kMagic );
159
165
SeaFlags flags (static_cast <SeaFlags>(ReadArithmetic<uint32_t >()));
160
166
Debug (" Read SEA flags %x\n " , static_cast <uint32_t >(flags));
167
+
168
+ uint8_t extension_value = ReadArithmetic<uint8_t >();
169
+ SeaExecArgvExtension exec_argv_extension =
170
+ static_cast <SeaExecArgvExtension>(extension_value);
171
+ Debug (" Read SEA resource exec argv extension %u\n " , extension_value);
161
172
CHECK_EQ (read_total, SeaResource::kHeaderSize );
162
173
163
174
std::string_view code_path =
@@ -212,7 +223,13 @@ SeaResource SeaDeserializer::Read() {
212
223
exec_argv.emplace_back (arg);
213
224
}
214
225
}
215
- return {flags, code_path, code, code_cache, assets, exec_argv};
226
+ return {flags,
227
+ exec_argv_extension,
228
+ code_path,
229
+ code,
230
+ code_cache,
231
+ assets,
232
+ exec_argv};
216
233
}
217
234
218
235
std::string_view FindSingleExecutableBlob () {
@@ -297,26 +314,55 @@ std::tuple<int, char**> FixupArgsForSEA(int argc, char** argv) {
297
314
if (IsSingleExecutable ()) {
298
315
static std::vector<char *> new_argv;
299
316
static std::vector<std::string> exec_argv_storage;
317
+ static std::vector<std::string> cli_extension_args;
300
318
301
319
SeaResource sea_resource = FindSingleExecutableResource ();
302
320
303
321
new_argv.clear ();
304
322
exec_argv_storage.clear ();
323
+ cli_extension_args.clear ();
324
+
325
+ // Handle CLI extension mode for --node-options
326
+ if (sea_resource.exec_argv_extension == SeaExecArgvExtension::kCli ) {
327
+ // Extract --node-options and filter argv
328
+ for (int i = 1 ; i < argc; ++i) {
329
+ if (strncmp (argv[i], " --node-options=" , 15 ) == 0 ) {
330
+ std::string node_options = argv[i] + 15 ;
331
+ std::vector<std::string> errors;
332
+ cli_extension_args = ParseNodeOptionsEnvVar (node_options, &errors);
333
+ // Remove this argument by shifting the rest
334
+ for (int j = i; j < argc - 1 ; ++j) {
335
+ argv[j] = argv[j + 1 ];
336
+ }
337
+ argc--;
338
+ i--; // Adjust index since we removed an element
339
+ }
340
+ }
341
+ }
305
342
306
- // Reserve space for argv[0], exec argv, original argv, and nullptr
307
- new_argv.reserve (argc + sea_resource.exec_argv .size () + 2 );
343
+ // Reserve space for argv[0], exec argv, cli extension args, original argv,
344
+ // and nullptr
345
+ new_argv.reserve (argc + sea_resource.exec_argv .size () +
346
+ cli_extension_args.size () + 2 );
308
347
new_argv.emplace_back (argv[0 ]);
309
348
310
349
// Insert exec argv from SEA config
311
350
if (!sea_resource.exec_argv .empty ()) {
312
- exec_argv_storage.reserve (sea_resource.exec_argv .size ());
351
+ exec_argv_storage.reserve (sea_resource.exec_argv .size () +
352
+ cli_extension_args.size ());
313
353
for (const auto & arg : sea_resource.exec_argv ) {
314
354
exec_argv_storage.emplace_back (arg);
315
355
new_argv.emplace_back (exec_argv_storage.back ().data ());
316
356
}
317
357
}
318
358
319
- // Add actual run time arguments.
359
+ // Insert CLI extension args
360
+ for (const auto & arg : cli_extension_args) {
361
+ exec_argv_storage.emplace_back (arg);
362
+ new_argv.emplace_back (exec_argv_storage.back ().data ());
363
+ }
364
+
365
+ // Add actual run time arguments
320
366
new_argv.insert (new_argv.end (), argv, argv + argc);
321
367
new_argv.emplace_back (nullptr );
322
368
argc = new_argv.size () - 1 ;
@@ -332,6 +378,7 @@ struct SeaConfig {
332
378
std::string main_path;
333
379
std::string output_path;
334
380
SeaFlags flags = SeaFlags::kDefault ;
381
+ SeaExecArgvExtension exec_argv_extension = SeaExecArgvExtension::kEnv ;
335
382
std::unordered_map<std::string, std::string> assets;
336
383
std::vector<std::string> exec_argv;
337
384
};
@@ -475,6 +522,27 @@ std::optional<SeaConfig> ParseSingleExecutableConfig(
475
522
result.flags |= SeaFlags::kIncludeExecArgv ;
476
523
result.exec_argv = std::move (exec_argv);
477
524
}
525
+ } else if (key == " execArgvExtension" ) {
526
+ std::string_view extension_str;
527
+ if (field.value ().get_string ().get (extension_str)) {
528
+ FPrintF (stderr,
529
+ " \" execArgvExtension\" field of %s is not a string\n " ,
530
+ config_path);
531
+ return std::nullopt;
532
+ }
533
+ if (extension_str == " none" ) {
534
+ result.exec_argv_extension = SeaExecArgvExtension::kNone ;
535
+ } else if (extension_str == " env" ) {
536
+ result.exec_argv_extension = SeaExecArgvExtension::kEnv ;
537
+ } else if (extension_str == " cli" ) {
538
+ result.exec_argv_extension = SeaExecArgvExtension::kCli ;
539
+ } else {
540
+ FPrintF (stderr,
541
+ " \" execArgvExtension\" field of %s must be one of "
542
+ " \" none\" , \" env\" , or \" cli\"\n " ,
543
+ config_path);
544
+ return std::nullopt;
545
+ }
478
546
}
479
547
}
480
548
@@ -674,6 +742,7 @@ ExitCode GenerateSingleExecutableBlob(
674
742
}
675
743
SeaResource sea{
676
744
config.flags ,
745
+ config.exec_argv_extension ,
677
746
config.main_path ,
678
747
builds_snapshot_from_main
679
748
? std::string_view{snapshot_blob.data (), snapshot_blob.size ()}
0 commit comments