@@ -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+ bool is_snapshotting,
9194 std::function<Environment*(const CommonEnvironmentSetup*)> make_env)
9295 : impl_(new Impl()) {
9396 CHECK_NOT_NULL (platform);
@@ -105,28 +108,42 @@ 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 (is_snapshotting) {
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 = is_snapshotting;
118135
119136 HandleScope handle_scope (isolate);
120137 if (snapshot_data) {
121138 impl_->env .reset (make_env (this ));
122139 if (impl_->env ) {
123- impl_->context .Reset (isolate, impl_->env ->context ());
140+ impl_->main_context .Reset (isolate, impl_->env ->context ());
124141 }
125142 return ;
126143 }
127144
128145 Local<Context> context = NewContext (isolate);
129- impl_->context .Reset (isolate, context);
146+ impl_->main_context .Reset (isolate, context);
130147 if (context.IsEmpty ()) {
131148 errors->push_back (" Failed to initialize V8 Context" );
132149 return ;
@@ -141,7 +158,34 @@ CommonEnvironmentSetup::CommonEnvironmentSetup(
141158 MultiIsolatePlatform* platform,
142159 std::vector<std::string>* errors,
143160 std::function<Environment*(const CommonEnvironmentSetup*)> make_env)
144- : CommonEnvironmentSetup(platform, errors, nullptr , make_env) {}
161+ : CommonEnvironmentSetup(platform, errors, nullptr , false , make_env) {}
162+
163+ std::unique_ptr<CommonEnvironmentSetup>
164+ CommonEnvironmentSetup::CreateForSnapshotting (
165+ MultiIsolatePlatform* platform,
166+ std::vector<std::string>* errors,
167+ const std::vector<std::string>& args,
168+ const std::vector<std::string>& exec_args) {
169+ // It's not guaranteed that a context that goes through
170+ // v8_inspector::V8Inspector::contextCreated() is runtime-independent,
171+ // so do not start the inspector on the main context when building
172+ // the default snapshot.
173+ uint64_t env_flags = EnvironmentFlags::kDefaultFlags |
174+ EnvironmentFlags::kNoCreateInspector ;
175+
176+ auto ret = std::unique_ptr<CommonEnvironmentSetup>(new CommonEnvironmentSetup (
177+ platform, errors, nullptr , true ,
178+ [&](const CommonEnvironmentSetup* setup) -> Environment* {
179+ return CreateEnvironment (
180+ setup->isolate_data (),
181+ setup->context (),
182+ args,
183+ exec_args,
184+ static_cast <EnvironmentFlags::Flags>(env_flags));
185+ }));
186+ if (!errors->empty ()) ret.reset ();
187+ return ret;
188+ }
145189
146190CommonEnvironmentSetup::~CommonEnvironmentSetup () {
147191 if (impl_->isolate != nullptr ) {
@@ -150,7 +194,7 @@ CommonEnvironmentSetup::~CommonEnvironmentSetup() {
150194 Locker locker (isolate);
151195 Isolate::Scope isolate_scope (isolate);
152196
153- impl_->context .Reset ();
197+ impl_->main_context .Reset ();
154198 impl_->env .reset ();
155199 impl_->isolate_data .reset ();
156200 }
@@ -160,7 +204,10 @@ CommonEnvironmentSetup::~CommonEnvironmentSetup() {
160204 *static_cast <bool *>(data) = true ;
161205 }, &platform_finished);
162206 impl_->platform ->UnregisterIsolate (isolate);
163- isolate->Dispose ();
207+ if (impl_->snapshot_creator .has_value ())
208+ impl_->snapshot_creator .reset ();
209+ else
210+ isolate->Dispose ();
164211
165212 // Wait until the platform has cleaned up all relevant resources.
166213 while (!platform_finished)
@@ -173,6 +220,20 @@ CommonEnvironmentSetup::~CommonEnvironmentSetup() {
173220 delete impl_;
174221}
175222
223+ EmbedderSnapshotData::Pointer CommonEnvironmentSetup::CreateSnapshot () {
224+ CHECK_NOT_NULL (snapshot_creator ());
225+ SnapshotData* snapshot_data = new SnapshotData ();
226+ EmbedderSnapshotData::Pointer result{
227+ new EmbedderSnapshotData (snapshot_data, true )};
228+
229+ auto exit_code = SnapshotBuilder::CreateSnapshot (
230+ snapshot_data, this ,
231+ static_cast <uint8_t >(SnapshotMetadata::Type::kFullyCustomized ));
232+ if (exit_code != ExitCode::kNoFailure ) return {};
233+
234+ return result;
235+ }
236+
176237Maybe<int > SpinEventLoop (Environment* env) {
177238 Maybe<ExitCode> result = SpinEventLoopInternal (env);
178239 if (result.IsNothing ()) {
@@ -203,7 +264,11 @@ Environment* CommonEnvironmentSetup::env() const {
203264}
204265
205266v8::Local<v8::Context> CommonEnvironmentSetup::context () const {
206- return impl_->context .Get (impl_->isolate );
267+ return impl_->main_context .Get (impl_->isolate );
268+ }
269+
270+ v8::SnapshotCreator* CommonEnvironmentSetup::snapshot_creator () {
271+ return impl_->snapshot_creator ? &impl_->snapshot_creator .value () : nullptr ;
207272}
208273
209274void EmbedderSnapshotData::DeleteSnapshotData::operator ()(
@@ -232,6 +297,10 @@ EmbedderSnapshotData::Pointer EmbedderSnapshotData::FromFile(FILE* in) {
232297 return result;
233298}
234299
300+ void EmbedderSnapshotData::ToFile (FILE* out) const {
301+ impl_->ToBlob (out);
302+ }
303+
235304EmbedderSnapshotData::EmbedderSnapshotData (const SnapshotData* impl,
236305 bool owns_impl)
237306 : impl_(impl), owns_impl_(owns_impl) {}
0 commit comments