@@ -14,6 +14,7 @@ using v8::Locker;
1414using v8::Maybe;
1515using v8::Nothing;
1616using v8::SealHandleScope;
17+ using v8::SnapshotCreator;
1718
1819namespace node {
1920
@@ -78,16 +79,18 @@ struct CommonEnvironmentSetup::Impl {
7879 MultiIsolatePlatform* platform = nullptr ;
7980 uv_loop_t loop;
8081 std::shared_ptr<ArrayBufferAllocator> allocator;
82+ std::optional<SnapshotCreator> snapshot_creator;
8183 Isolate* isolate = nullptr ;
8284 DeleteFnPtr<IsolateData, FreeIsolateData> isolate_data;
8385 DeleteFnPtr<Environment, FreeEnvironment> env;
84- Global<Context> context ;
86+ Global<Context> main_context ;
8587};
8688
8789CommonEnvironmentSetup::CommonEnvironmentSetup (
8890 MultiIsolatePlatform* platform,
8991 std::vector<std::string>* errors,
9092 const EmbedderSnapshotData* snapshot_data,
93+ uint32_t flags,
9194 std::function<Environment*(const CommonEnvironmentSetup*)> make_env)
9295 : impl_(new Impl()) {
9396 CHECK_NOT_NULL (platform);
@@ -105,28 +108,43 @@ CommonEnvironmentSetup::CommonEnvironmentSetup(
105108 }
106109 loop->data = this ;
107110
108- impl_->allocator = ArrayBufferAllocator::Create ();
109- impl_->isolate =
110- NewIsolate (impl_->allocator , &impl_->loop , platform, snapshot_data);
111- Isolate* isolate = impl_->isolate ;
111+ Isolate* isolate;
112+ if (flags & Flags::kIsForSnapshotting ) {
113+ const std::vector<intptr_t >& external_references =
114+ SnapshotBuilder::CollectExternalReferences ();
115+ isolate = impl_->isolate = Isolate::Allocate ();
116+ // Must be done before the SnapshotCreator creation so that the
117+ // memory reducer can be initialized.
118+ platform->RegisterIsolate (isolate, loop);
119+ impl_->snapshot_creator .emplace (isolate, external_references.data ());
120+ isolate->SetCaptureStackTraceForUncaughtExceptions (
121+ true , 10 , v8::StackTrace::StackTraceOptions::kDetailed );
122+ SetIsolateMiscHandlers (isolate, {});
123+ } else {
124+ impl_->allocator = ArrayBufferAllocator::Create ();
125+ isolate = impl_->isolate =
126+ NewIsolate (impl_->allocator , &impl_->loop , platform, snapshot_data);
127+ }
112128
113129 {
114130 Locker locker (isolate);
115131 Isolate::Scope isolate_scope (isolate);
116132 impl_->isolate_data .reset (CreateIsolateData (
117133 isolate, loop, platform, impl_->allocator .get (), snapshot_data));
134+ impl_->isolate_data ->options ()->build_snapshot =
135+ impl_->snapshot_creator .has_value ();
118136
119137 HandleScope handle_scope (isolate);
120138 if (snapshot_data) {
121139 impl_->env .reset (make_env (this ));
122140 if (impl_->env ) {
123- impl_->context .Reset (isolate, impl_->env ->context ());
141+ impl_->main_context .Reset (isolate, impl_->env ->context ());
124142 }
125143 return ;
126144 }
127145
128146 Local<Context> context = NewContext (isolate);
129- impl_->context .Reset (isolate, context);
147+ impl_->main_context .Reset (isolate, context);
130148 if (context.IsEmpty ()) {
131149 errors->push_back (" Failed to initialize V8 Context" );
132150 return ;
@@ -141,7 +159,37 @@ CommonEnvironmentSetup::CommonEnvironmentSetup(
141159 MultiIsolatePlatform* platform,
142160 std::vector<std::string>* errors,
143161 std::function<Environment*(const CommonEnvironmentSetup*)> make_env)
144- : CommonEnvironmentSetup(platform, errors, nullptr , make_env) {}
162+ : CommonEnvironmentSetup(platform, errors, nullptr , false , make_env) {}
163+
164+ std::unique_ptr<CommonEnvironmentSetup>
165+ CommonEnvironmentSetup::CreateForSnapshotting (
166+ MultiIsolatePlatform* platform,
167+ std::vector<std::string>* errors,
168+ const std::vector<std::string>& args,
169+ const std::vector<std::string>& exec_args) {
170+ // It's not guaranteed that a context that goes through
171+ // v8_inspector::V8Inspector::contextCreated() is runtime-independent,
172+ // so do not start the inspector on the main context when building
173+ // the default snapshot.
174+ uint64_t env_flags =
175+ EnvironmentFlags::kDefaultFlags | EnvironmentFlags::kNoCreateInspector ;
176+
177+ auto ret = std::unique_ptr<CommonEnvironmentSetup>(new CommonEnvironmentSetup (
178+ platform,
179+ errors,
180+ nullptr ,
181+ true ,
182+ [&](const CommonEnvironmentSetup* setup) -> Environment* {
183+ return CreateEnvironment (
184+ setup->isolate_data (),
185+ setup->context (),
186+ args,
187+ exec_args,
188+ static_cast <EnvironmentFlags::Flags>(env_flags));
189+ }));
190+ if (!errors->empty ()) ret.reset ();
191+ return ret;
192+ }
145193
146194CommonEnvironmentSetup::~CommonEnvironmentSetup () {
147195 if (impl_->isolate != nullptr ) {
@@ -150,7 +198,7 @@ CommonEnvironmentSetup::~CommonEnvironmentSetup() {
150198 Locker locker (isolate);
151199 Isolate::Scope isolate_scope (isolate);
152200
153- impl_->context .Reset ();
201+ impl_->main_context .Reset ();
154202 impl_->env .reset ();
155203 impl_->isolate_data .reset ();
156204 }
@@ -160,7 +208,10 @@ CommonEnvironmentSetup::~CommonEnvironmentSetup() {
160208 *static_cast <bool *>(data) = true ;
161209 }, &platform_finished);
162210 impl_->platform ->UnregisterIsolate (isolate);
163- isolate->Dispose ();
211+ if (impl_->snapshot_creator .has_value ())
212+ impl_->snapshot_creator .reset ();
213+ else
214+ isolate->Dispose ();
164215
165216 // Wait until the platform has cleaned up all relevant resources.
166217 while (!platform_finished)
@@ -173,6 +224,21 @@ CommonEnvironmentSetup::~CommonEnvironmentSetup() {
173224 delete impl_;
174225}
175226
227+ EmbedderSnapshotData::Pointer CommonEnvironmentSetup::CreateSnapshot () {
228+ CHECK_NOT_NULL (snapshot_creator ());
229+ SnapshotData* snapshot_data = new SnapshotData ();
230+ EmbedderSnapshotData::Pointer result{
231+ new EmbedderSnapshotData (snapshot_data, true )};
232+
233+ auto exit_code = SnapshotBuilder::CreateSnapshot (
234+ snapshot_data,
235+ this ,
236+ static_cast <uint8_t >(SnapshotMetadata::Type::kFullyCustomized ));
237+ if (exit_code != ExitCode::kNoFailure ) return {};
238+
239+ return result;
240+ }
241+
176242Maybe<int > SpinEventLoop (Environment* env) {
177243 Maybe<ExitCode> result = SpinEventLoopInternal (env);
178244 if (result.IsNothing ()) {
@@ -203,7 +269,11 @@ Environment* CommonEnvironmentSetup::env() const {
203269}
204270
205271v8::Local<v8::Context> CommonEnvironmentSetup::context () const {
206- return impl_->context .Get (impl_->isolate );
272+ return impl_->main_context .Get (impl_->isolate );
273+ }
274+
275+ v8::SnapshotCreator* CommonEnvironmentSetup::snapshot_creator () {
276+ return impl_->snapshot_creator ? &impl_->snapshot_creator .value () : nullptr ;
207277}
208278
209279void EmbedderSnapshotData::DeleteSnapshotData::operator ()(
@@ -232,6 +302,10 @@ EmbedderSnapshotData::Pointer EmbedderSnapshotData::FromFile(FILE* in) {
232302 return result;
233303}
234304
305+ void EmbedderSnapshotData::ToFile (FILE* out) const {
306+ impl_->ToBlob (out);
307+ }
308+
235309EmbedderSnapshotData::EmbedderSnapshotData (const SnapshotData* impl,
236310 bool owns_impl)
237311 : impl_(impl), owns_impl_(owns_impl) {}
0 commit comments