sea: support execArgv in sea config · nodejs/node@c6e3d5d
@@ -123,6 +123,18 @@ size_t SeaSerializer::Write(const SeaResource& sea) {
123123 written_total += WriteStringView(content, StringLogMode::kAddressOnly);
124124 }
125125 }
126+127+if (static_cast<bool>(sea.flags & SeaFlags::kIncludeExecArgv)) {
128+Debug("Write SEA resource exec argv size %zu\n", sea.exec_argv.size());
129+ written_total += WriteArithmetic<size_t>(sea.exec_argv.size());
130+for (const auto& arg : sea.exec_argv) {
131+Debug("Write SEA resource exec arg %s at %p, size=%zu\n",
132+ arg.data(),
133+ arg.data(),
134+ arg.size());
135+ written_total += WriteStringView(arg, StringLogMode::kAddressAndContent);
136+ }
137+ }
126138return written_total;
127139}
128140@@ -185,7 +197,22 @@ SeaResource SeaDeserializer::Read() {
185197 assets.emplace(key, content);
186198 }
187199 }
188-return {flags, code_path, code, code_cache, assets};
200+201+ std::vector<std::string_view> exec_argv;
202+if (static_cast<bool>(flags & SeaFlags::kIncludeExecArgv)) {
203+size_t exec_argv_size = ReadArithmetic<size_t>();
204+Debug("Read SEA resource exec args size %zu\n", exec_argv_size);
205+ exec_argv.reserve(exec_argv_size);
206+for (size_t i = 0; i < exec_argv_size; ++i) {
207+ std::string_view arg = ReadStringView(StringLogMode::kAddressAndContent);
208+Debug("Read SEA resource exec arg %s at %p, size=%zu\n",
209+ arg.data(),
210+ arg.data(),
211+ arg.size());
212+ exec_argv.emplace_back(arg);
213+ }
214+ }
215+return {flags, code_path, code, code_cache, assets, exec_argv};
189216}
190217191218std::string_view FindSingleExecutableBlob() {
@@ -269,8 +296,27 @@ std::tuple<int, char**> FixupArgsForSEA(int argc, char** argv) {
269296// entry point file path.
270297if (IsSingleExecutable()) {
271298static std::vector<char*> new_argv;
272- new_argv.reserve(argc + 2);
299+static std::vector<std::string> exec_argv_storage;
300+301+ SeaResource sea_resource = FindSingleExecutableResource();
302+303+ new_argv.clear();
304+ exec_argv_storage.clear();
305+306+// Reserve space for argv[0], exec argv, original argv, and nullptr
307+ new_argv.reserve(argc + sea_resource.exec_argv.size() + 2);
273308 new_argv.emplace_back(argv[0]);
309+310+// Insert exec argv from SEA config
311+if (!sea_resource.exec_argv.empty()) {
312+ exec_argv_storage.reserve(sea_resource.exec_argv.size());
313+for (const auto& arg : sea_resource.exec_argv) {
314+ exec_argv_storage.emplace_back(arg);
315+ new_argv.emplace_back(exec_argv_storage.back().data());
316+ }
317+ }
318+319+// Add actual run time arguments.
274320 new_argv.insert(new_argv.end(), argv, argv + argc);
275321 new_argv.emplace_back(nullptr);
276322 argc = new_argv.size() - 1;
@@ -287,6 +333,7 @@ struct SeaConfig {
287333 std::string output_path;
288334 SeaFlags flags = SeaFlags::kDefault;
289335 std::unordered_map<std::string, std::string> assets;
336+ std::vector<std::string> exec_argv;
290337};
291338292339std::optional<SeaConfig> ParseSingleExecutableConfig(
@@ -405,6 +452,29 @@ std::optional<SeaConfig> ParseSingleExecutableConfig(
405452if (!result.assets.empty()) {
406453 result.flags |= SeaFlags::kIncludeAssets;
407454 }
455+ } else if (key == "execArgv") {
456+ simdjson::ondemand::array exec_argv_array;
457+if (field.value().get_array().get(exec_argv_array)) {
458+FPrintF(stderr,
459+"\"execArgv\" field of %s is not an array of strings\n",
460+ config_path);
461+return std::nullopt;
462+ }
463+ std::vector<std::string> exec_argv;
464+for (auto argv : exec_argv_array) {
465+ std::string_view argv_str;
466+if (argv.get_string().get(argv_str)) {
467+FPrintF(stderr,
468+"\"execArgv\" field of %s is not an array of strings\n",
469+ config_path);
470+return std::nullopt;
471+ }
472+ exec_argv.emplace_back(argv_str);
473+ }
474+if (!exec_argv.empty()) {
475+ result.flags |= SeaFlags::kIncludeExecArgv;
476+ result.exec_argv = std::move(exec_argv);
477+ }
408478 }
409479 }
410480@@ -598,14 +668,19 @@ ExitCode GenerateSingleExecutableBlob(
598668for (auto const& [key, content] : assets) {
599669 assets_view.emplace(key, content);
600670 }
671+ std::vector<std::string_view> exec_argv_view;
672+for (const auto& arg : config.exec_argv) {
673+ exec_argv_view.emplace_back(arg);
674+ }
601675 SeaResource sea{
602676 config.flags,
603677 config.main_path,
604678 builds_snapshot_from_main
605679 ? std::string_view{snapshot_blob.data(), snapshot_blob.size()}
606680 : std::string_view{main_script.data(), main_script.size()},
607681 optional_sv_code_cache,
608- assets_view};
682+ assets_view,
683+ exec_argv_view};
609684610685 SeaSerializer serializer;
611686 serializer.Write(sea);