66#include " json_parser.h"
77#include " node_external_reference.h"
88#include " node_internals.h"
9+ #include " node_snapshot_builder.h"
910#include " node_union_bytes.h"
11+ #include " node_v8_platform-inl.h"
1012
1113// The POSTJECT_SENTINEL_FUSE macro is a string of random characters selected by
1214// the Node.js project that is present only once in the entire binary. It is
2729using node::ExitCode;
2830using v8::Context;
2931using v8::FunctionCallbackInfo;
32+ using v8::HandleScope;
33+ using v8::Isolate;
3034using v8::Local;
35+ using v8::Locker;
3136using v8::Object;
3237using v8::Value;
3338
@@ -64,7 +69,7 @@ class SeaSerializer : public BlobSerializer<SeaSerializer> {
6469
6570template <>
6671size_t SeaSerializer::Write (const SeaResource& sea) {
67- sink.reserve (SeaResource::kHeaderSize + sea.code .size ());
72+ sink.reserve (SeaResource::kHeaderSize + sea.main_code_or_snapshot .size ());
6873
6974 Debug (" Write SEA magic %x\n " , kMagic );
7075 size_t written_total = WriteArithmetic<uint32_t >(kMagic );
@@ -75,9 +80,12 @@ size_t SeaSerializer::Write(const SeaResource& sea) {
7580 DCHECK_EQ (written_total, SeaResource::kHeaderSize );
7681
7782 Debug (" Write SEA resource code %p, size=%zu\n " ,
78- sea.code .data (),
79- sea.code .size ());
80- written_total += WriteStringView (sea.code , StringLogMode::kAddressAndContent );
83+ sea.main_code_or_snapshot .data (),
84+ sea.main_code_or_snapshot .size ());
85+ written_total +=
86+ WriteStringView (sea.main_code_or_snapshot ,
87+ sea.use_snapshot () ? StringLogMode::kAddressOnly
88+ : StringLogMode::kAddressAndContent );
8189 return written_total;
8290}
8391
@@ -103,7 +111,10 @@ SeaResource SeaDeserializer::Read() {
103111 Debug (" Read SEA flags %x\n " , static_cast <uint32_t >(flags));
104112 CHECK_EQ (read_total, SeaResource::kHeaderSize );
105113
106- std::string_view code = ReadStringView (StringLogMode::kAddressAndContent );
114+ std::string_view code =
115+ ReadStringView (static_cast <bool >(flags & SeaFlags::kuseSnapshot)
116+ ? StringLogMode::kAddressOnly
117+ : StringLogMode::kAddressAndContent );
107118 Debug (" Read SEA resource code %p, size=%zu\n " , code.data (), code.size ());
108119 return {flags, code};
109120}
@@ -133,6 +144,10 @@ std::string_view FindSingleExecutableBlob() {
133144
134145} // anonymous namespace
135146
147+ bool SeaResource::use_snapshot () const {
148+ return static_cast <bool >(flags & SeaFlags::kuseSnapshot);
149+ }
150+
136151SeaResource FindSingleExecutableResource () {
137152 static const SeaResource sea_resource = []() -> SeaResource {
138153 std::string_view blob = FindSingleExecutableBlob ();
@@ -235,10 +250,23 @@ std::optional<SeaConfig> ParseSingleExecutableConfig(
235250 result.flags |= SeaFlags::kDisableExperimentalSeaWarning ;
236251 }
237252
253+ std::optional<bool > use_snapshot = parser.GetTopLevelBoolField (" useSnapshot" );
254+ if (!use_snapshot.has_value ()) {
255+ FPrintF (
256+ stderr, " \" useSnapshot\" field of %s is not a Boolean\n " , config_path);
257+ return std::nullopt ;
258+ }
259+ if (use_snapshot.value ()) {
260+ result.flags |= SeaFlags::kuseSnapshot;
261+ }
262+
238263 return result;
239264}
240265
241- ExitCode GenerateSingleExecutableBlob (const SeaConfig& config) {
266+ ExitCode GenerateSingleExecutableBlob (
267+ const SeaConfig& config,
268+ const std::vector<std::string> args,
269+ const std::vector<std::string> exec_args) {
242270 std::string main_script;
243271 // TODO(joyeecheung): unify the file utils.
244272 int r = ReadFileSync (&main_script, config.main_path .c_str ());
@@ -248,7 +276,25 @@ ExitCode GenerateSingleExecutableBlob(const SeaConfig& config) {
248276 return ExitCode::kGenericUserError ;
249277 }
250278
251- SeaResource sea{config.flags , main_script};
279+ std::vector<char > snapshot_blob;
280+ bool builds_snapshot_from_main =
281+ static_cast <bool >(config.flags & SeaFlags::kuseSnapshot);
282+ if (builds_snapshot_from_main) {
283+ SnapshotData snapshot;
284+ std::vector<std::string> patched_args = {args[0 ], GetAnonymousMainPath ()};
285+ ExitCode exit_code = SnapshotBuilder::Generate (
286+ &snapshot, patched_args, exec_args, main_script);
287+ if (exit_code != ExitCode::kNoFailure ) {
288+ return exit_code;
289+ }
290+ snapshot.ToBlob (&snapshot_blob);
291+ }
292+
293+ SeaResource sea{
294+ config.flags ,
295+ builds_snapshot_from_main
296+ ? std::string_view{snapshot_blob.data (), snapshot_blob.size ()}
297+ : std::string_view{main_script.data (), main_script.size ()}};
252298
253299 SeaSerializer serializer;
254300 serializer.Write (sea);
@@ -269,11 +315,14 @@ ExitCode GenerateSingleExecutableBlob(const SeaConfig& config) {
269315
270316} // anonymous namespace
271317
272- ExitCode BuildSingleExecutableBlob (const std::string& config_path) {
318+ ExitCode BuildSingleExecutableBlob (const std::string& config_path,
319+ const std::vector<std::string> args,
320+ const std::vector<std::string> exec_args) {
273321 std::optional<SeaConfig> config_opt =
274322 ParseSingleExecutableConfig (config_path);
275323 if (config_opt.has_value ()) {
276- ExitCode code = GenerateSingleExecutableBlob (config_opt.value ());
324+ ExitCode code =
325+ GenerateSingleExecutableBlob (config_opt.value (), args, exec_args);
277326 return code;
278327 }
279328
0 commit comments