@@ -14,6 +14,7 @@ using v8::Locker;
14
14
using v8::Maybe;
15
15
using v8::Nothing;
16
16
using v8::SealHandleScope;
17
+ using v8::SnapshotCreator;
17
18
18
19
namespace node {
19
20
@@ -78,16 +79,18 @@ struct CommonEnvironmentSetup::Impl {
78
79
MultiIsolatePlatform* platform = nullptr ;
79
80
uv_loop_t loop;
80
81
std::shared_ptr<ArrayBufferAllocator> allocator;
82
+ std::optional<SnapshotCreator> snapshot_creator;
81
83
Isolate* isolate = nullptr ;
82
84
DeleteFnPtr<IsolateData, FreeIsolateData> isolate_data;
83
85
DeleteFnPtr<Environment, FreeEnvironment> env;
84
- Global<Context> context ;
86
+ Global<Context> main_context ;
85
87
};
86
88
87
89
CommonEnvironmentSetup::CommonEnvironmentSetup (
88
90
MultiIsolatePlatform* platform,
89
91
std::vector<std::string>* errors,
90
92
const EmbedderSnapshotData* snapshot_data,
93
+ uint32_t flags,
91
94
std::function<Environment*(const CommonEnvironmentSetup*)> make_env)
92
95
: impl_(new Impl()) {
93
96
CHECK_NOT_NULL (platform);
@@ -105,28 +108,43 @@ CommonEnvironmentSetup::CommonEnvironmentSetup(
105
108
}
106
109
loop->data = this ;
107
110
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
+ }
112
128
113
129
{
114
130
Locker locker (isolate);
115
131
Isolate::Scope isolate_scope (isolate);
116
132
impl_->isolate_data .reset (CreateIsolateData (
117
133
isolate, loop, platform, impl_->allocator .get (), snapshot_data));
134
+ impl_->isolate_data ->options ()->build_snapshot =
135
+ impl_->snapshot_creator .has_value ();
118
136
119
137
HandleScope handle_scope (isolate);
120
138
if (snapshot_data) {
121
139
impl_->env .reset (make_env (this ));
122
140
if (impl_->env ) {
123
- impl_->context .Reset (isolate, impl_->env ->context ());
141
+ impl_->main_context .Reset (isolate, impl_->env ->context ());
124
142
}
125
143
return ;
126
144
}
127
145
128
146
Local<Context> context = NewContext (isolate);
129
- impl_->context .Reset (isolate, context);
147
+ impl_->main_context .Reset (isolate, context);
130
148
if (context.IsEmpty ()) {
131
149
errors->push_back (" Failed to initialize V8 Context" );
132
150
return ;
@@ -141,7 +159,37 @@ CommonEnvironmentSetup::CommonEnvironmentSetup(
141
159
MultiIsolatePlatform* platform,
142
160
std::vector<std::string>* errors,
143
161
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
+ }
145
193
146
194
CommonEnvironmentSetup::~CommonEnvironmentSetup () {
147
195
if (impl_->isolate != nullptr ) {
@@ -150,7 +198,7 @@ CommonEnvironmentSetup::~CommonEnvironmentSetup() {
150
198
Locker locker (isolate);
151
199
Isolate::Scope isolate_scope (isolate);
152
200
153
- impl_->context .Reset ();
201
+ impl_->main_context .Reset ();
154
202
impl_->env .reset ();
155
203
impl_->isolate_data .reset ();
156
204
}
@@ -160,7 +208,10 @@ CommonEnvironmentSetup::~CommonEnvironmentSetup() {
160
208
*static_cast <bool *>(data) = true ;
161
209
}, &platform_finished);
162
210
impl_->platform ->UnregisterIsolate (isolate);
163
- isolate->Dispose ();
211
+ if (impl_->snapshot_creator .has_value ())
212
+ impl_->snapshot_creator .reset ();
213
+ else
214
+ isolate->Dispose ();
164
215
165
216
// Wait until the platform has cleaned up all relevant resources.
166
217
while (!platform_finished)
@@ -173,6 +224,21 @@ CommonEnvironmentSetup::~CommonEnvironmentSetup() {
173
224
delete impl_;
174
225
}
175
226
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
+
176
242
Maybe<int > SpinEventLoop (Environment* env) {
177
243
Maybe<ExitCode> result = SpinEventLoopInternal (env);
178
244
if (result.IsNothing ()) {
@@ -203,7 +269,11 @@ Environment* CommonEnvironmentSetup::env() const {
203
269
}
204
270
205
271
v8::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 ;
207
277
}
208
278
209
279
void EmbedderSnapshotData::DeleteSnapshotData::operator ()(
@@ -232,6 +302,10 @@ EmbedderSnapshotData::Pointer EmbedderSnapshotData::FromFile(FILE* in) {
232
302
return result;
233
303
}
234
304
305
+ void EmbedderSnapshotData::ToFile (FILE* out) const {
306
+ impl_->ToBlob (out);
307
+ }
308
+
235
309
EmbedderSnapshotData::EmbedderSnapshotData (const SnapshotData* impl,
236
310
bool owns_impl)
237
311
: impl_(impl), owns_impl_(owns_impl) {}
0 commit comments