6
6
#include " json_parser.h"
7
7
#include " node_external_reference.h"
8
8
#include " node_internals.h"
9
+ #include " node_snapshot_builder.h"
9
10
#include " node_union_bytes.h"
11
+ #include " node_v8_platform-inl.h"
10
12
11
13
// The POSTJECT_SENTINEL_FUSE macro is a string of random characters selected by
12
14
// the Node.js project that is present only once in the entire binary. It is
27
29
using node::ExitCode;
28
30
using v8::Context;
29
31
using v8::FunctionCallbackInfo;
32
+ using v8::HandleScope;
33
+ using v8::Isolate;
30
34
using v8::Local;
35
+ using v8::Locker;
31
36
using v8::Object;
32
37
using v8::Value;
33
38
@@ -64,7 +69,7 @@ class SeaSerializer : public BlobSerializer<SeaSerializer> {
64
69
65
70
template <>
66
71
size_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 ());
68
73
69
74
Debug (" Write SEA magic %x\n " , kMagic );
70
75
size_t written_total = WriteArithmetic<uint32_t >(kMagic );
@@ -75,9 +80,12 @@ size_t SeaSerializer::Write(const SeaResource& sea) {
75
80
DCHECK_EQ (written_total, SeaResource::kHeaderSize );
76
81
77
82
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 );
81
89
return written_total;
82
90
}
83
91
@@ -103,7 +111,10 @@ SeaResource SeaDeserializer::Read() {
103
111
Debug (" Read SEA flags %x\n " , static_cast <uint32_t >(flags));
104
112
CHECK_EQ (read_total, SeaResource::kHeaderSize );
105
113
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 );
107
118
Debug (" Read SEA resource code %p, size=%zu\n " , code.data (), code.size ());
108
119
return {flags, code};
109
120
}
@@ -133,6 +144,10 @@ std::string_view FindSingleExecutableBlob() {
133
144
134
145
} // anonymous namespace
135
146
147
+ bool SeaResource::use_snapshot () const {
148
+ return static_cast <bool >(flags & SeaFlags::kuseSnapshot);
149
+ }
150
+
136
151
SeaResource FindSingleExecutableResource () {
137
152
static const SeaResource sea_resource = []() -> SeaResource {
138
153
std::string_view blob = FindSingleExecutableBlob ();
@@ -235,10 +250,23 @@ std::optional<SeaConfig> ParseSingleExecutableConfig(
235
250
result.flags |= SeaFlags::kDisableExperimentalSeaWarning ;
236
251
}
237
252
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
+
238
263
return result;
239
264
}
240
265
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) {
242
270
std::string main_script;
243
271
// TODO(joyeecheung): unify the file utils.
244
272
int r = ReadFileSync (&main_script, config.main_path .c_str ());
@@ -248,7 +276,25 @@ ExitCode GenerateSingleExecutableBlob(const SeaConfig& config) {
248
276
return ExitCode::kGenericUserError ;
249
277
}
250
278
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 ()}};
252
298
253
299
SeaSerializer serializer;
254
300
serializer.Write (sea);
@@ -269,11 +315,14 @@ ExitCode GenerateSingleExecutableBlob(const SeaConfig& config) {
269
315
270
316
} // anonymous namespace
271
317
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) {
273
321
std::optional<SeaConfig> config_opt =
274
322
ParseSingleExecutableConfig (config_path);
275
323
if (config_opt.has_value ()) {
276
- ExitCode code = GenerateSingleExecutableBlob (config_opt.value ());
324
+ ExitCode code =
325
+ GenerateSingleExecutableBlob (config_opt.value (), args, exec_args);
277
326
return code;
278
327
}
279
328
0 commit comments