@@ -292,6 +292,17 @@ MaybeLocal<Value> StartExecution(Environment* env, StartExecutionCallback cb) {
292292
293293 CHECK (!env->isolate_data ()->is_building_snapshot ());
294294
295+ #ifndef DISABLE_SINGLE_EXECUTABLE_APPLICATION
296+ if (sea::IsSingleExecutable ()) {
297+ sea::SeaResource sea = sea::FindSingleExecutableResource ();
298+ // The SEA preparation blob building process should already enforce this,
299+ // this check is just here to guard against the unlikely case where
300+ // the SEA preparation blob has been manually modified by someone.
301+ CHECK_IMPLIES (sea.use_snapshot (),
302+ !env->snapshot_deserialize_main ().IsEmpty ());
303+ }
304+ #endif
305+
295306 // TODO(joyeecheung): move these conditions into JS land and let the
296307 // deserialize main function take precedence. For workers, we need to
297308 // move the pre-execution part into a different file that can be
@@ -1198,49 +1209,66 @@ ExitCode GenerateAndWriteSnapshotData(const SnapshotData** snapshot_data_ptr,
11981209 return exit_code;
11991210}
12001211
1201- ExitCode LoadSnapshotDataAndRun (const SnapshotData** snapshot_data_ptr,
1202- const InitializationResultImpl* result) {
1203- ExitCode exit_code = result->exit_code_enum ();
1212+ bool LoadSnapshotData (const SnapshotData** snapshot_data_ptr) {
12041213 // nullptr indicates there's no snapshot data.
12051214 DCHECK_NULL (*snapshot_data_ptr);
1215+
1216+ bool is_sea = false ;
1217+ #ifndef DISABLE_SINGLE_EXECUTABLE_APPLICATION
1218+ if (sea::IsSingleExecutable ()) {
1219+ is_sea = true ;
1220+ sea::SeaResource sea = sea::FindSingleExecutableResource ();
1221+ if (sea.use_snapshot ()) {
1222+ std::unique_ptr<SnapshotData> read_data =
1223+ std::make_unique<SnapshotData>();
1224+ std::string_view snapshot = sea.main_code_or_snapshot ;
1225+ if (SnapshotData::FromBlob (read_data.get (), snapshot)) {
1226+ *snapshot_data_ptr = read_data.release ();
1227+ return true ;
1228+ } else {
1229+ fprintf (stderr, " Invalid snapshot data in single executable binary\n " );
1230+ return false ;
1231+ }
1232+ }
1233+ }
1234+ #endif
1235+
12061236 // --snapshot-blob indicates that we are reading a customized snapshot.
1207- if (!per_process::cli_options->snapshot_blob .empty ()) {
1237+ // Ignore it when we are loading from SEA.
1238+ if (!is_sea && !per_process::cli_options->snapshot_blob .empty ()) {
12081239 std::string filename = per_process::cli_options->snapshot_blob ;
12091240 FILE* fp = fopen (filename.c_str (), " rb" );
12101241 if (fp == nullptr ) {
12111242 fprintf (stderr, " Cannot open %s" , filename.c_str ());
1212- exit_code = ExitCode::kStartupSnapshotFailure ;
1213- return exit_code;
1243+ return false ;
12141244 }
12151245 std::unique_ptr<SnapshotData> read_data = std::make_unique<SnapshotData>();
12161246 bool ok = SnapshotData::FromFile (read_data.get (), fp);
12171247 fclose (fp);
12181248 if (!ok) {
1219- // If we fail to read the customized snapshot,
1220- // simply exit with kStartupSnapshotFailure.
1221- exit_code = ExitCode::kStartupSnapshotFailure ;
1222- return exit_code;
1249+ return false ;
12231250 }
12241251 *snapshot_data_ptr = read_data.release ();
1225- } else if (per_process::cli_options->node_snapshot ) {
1226- // If --snapshot-blob is not specified, we are reading the embedded
1227- // snapshot, but we will skip it if --no-node-snapshot is specified.
1252+ return true ;
1253+ }
1254+
1255+ if (per_process::cli_options->node_snapshot ) {
1256+ // If --snapshot-blob is not specified or if the SEA contains no snapshot,
1257+ // we are reading the embedded snapshot, but we will skip it if
1258+ // --no-node-snapshot is specified.
12281259 const node::SnapshotData* read_data =
12291260 SnapshotBuilder::GetEmbeddedSnapshotData ();
1230- if (read_data != nullptr && read_data->Check ()) {
1261+ if (read_data != nullptr ) {
1262+ if (!read_data->Check ()) {
1263+ return false ;
1264+ }
12311265 // If we fail to read the embedded snapshot, treat it as if Node.js
12321266 // was built without one.
12331267 *snapshot_data_ptr = read_data;
12341268 }
12351269 }
12361270
1237- NodeMainInstance main_instance (*snapshot_data_ptr,
1238- uv_default_loop (),
1239- per_process::v8_platform.Platform (),
1240- result->args (),
1241- result->exec_args ());
1242- exit_code = main_instance.Run ();
1243- return exit_code;
1271+ return true ;
12441272}
12451273
12461274static ExitCode StartInternal (int argc, char ** argv) {
@@ -1275,7 +1303,8 @@ static ExitCode StartInternal(int argc, char** argv) {
12751303
12761304 std::string sea_config = per_process::cli_options->experimental_sea_config ;
12771305 if (!sea_config.empty ()) {
1278- return sea::BuildSingleExecutableBlob (sea_config);
1306+ return sea::BuildSingleExecutableBlob (
1307+ sea_config, result->args (), result->exec_args ());
12791308 }
12801309
12811310 // --build-snapshot indicates that we are in snapshot building mode.
@@ -1290,7 +1319,15 @@ static ExitCode StartInternal(int argc, char** argv) {
12901319 }
12911320
12921321 // Without --build-snapshot, we are in snapshot loading mode.
1293- return LoadSnapshotDataAndRun (&snapshot_data, result.get ());
1322+ if (!LoadSnapshotData (&snapshot_data)) {
1323+ return ExitCode::kStartupSnapshotFailure ;
1324+ }
1325+ NodeMainInstance main_instance (snapshot_data,
1326+ uv_default_loop (),
1327+ per_process::v8_platform.Platform (),
1328+ result->args (),
1329+ result->exec_args ());
1330+ return main_instance.Run ();
12941331}
12951332
12961333int Start (int argc, char ** argv) {
0 commit comments