1use crate::Context;
2use crate::Data;
3use crate::Local;
4use crate::OwnedIsolate;
5use crate::external_references::ExternalReference;
6use crate::isolate::RealIsolate;
7use crate::isolate_create_params::raw;
8use crate::support::char;
9use crate::support::int;
10
11use std::borrow::Cow;
12use std::mem::MaybeUninit;
13
14unsafe extern "C" {
15 fn v8__SnapshotCreator__CONSTRUCT(
16 buf: *mut MaybeUninit<SnapshotCreator>,
17 params: *const raw::CreateParams,
18 );
19 fn v8__SnapshotCreator__DESTRUCT(this: *mut SnapshotCreator);
20 fn v8__SnapshotCreator__GetIsolate(
21 this: *const SnapshotCreator,
22 ) -> *mut RealIsolate;
23 fn v8__SnapshotCreator__CreateBlob(
24 this: *mut SnapshotCreator,
25 function_code_handling: FunctionCodeHandling,
26 ) -> RawStartupData;
27 fn v8__SnapshotCreator__SetDefaultContext(
28 this: *mut SnapshotCreator,
29 context: *const Context,
30 );
31 fn v8__SnapshotCreator__AddContext(
32 this: *mut SnapshotCreator,
33 context: *const Context,
34 ) -> usize;
35 fn v8__SnapshotCreator__AddData_to_isolate(
36 this: *mut SnapshotCreator,
37 data: *const Data,
38 ) -> usize;
39 fn v8__SnapshotCreator__AddData_to_context(
40 this: *mut SnapshotCreator,
41 context: *const Context,
42 data: *const Data,
43 ) -> usize;
44 fn v8__StartupData__CanBeRehashed(this: *const RawStartupData) -> bool;
45 fn v8__StartupData__IsValid(this: *const RawStartupData) -> bool;
46 fn v8__StartupData__data__DELETE(this: *const char);
47}
48
49#[repr(C)]
50#[derive(Debug, Clone, Copy)]
51pub(crate) struct RawStartupData {
52 pub(crate) data: *const char,
53 pub(crate) raw_size: int,
54}
55
56#[derive(Debug, Clone)]
57pub struct StartupData(StartupDataInner);
58
59#[derive(Debug)]
60enum StartupDataInner {
61 Cpp(RawStartupData),
62 Cow(Cow<'static, [u8]>),
63}
64
65impl StartupData {
66 pub fn can_be_rehashed(&self) -> bool {
70 let tmp = match &self.0 {
71 StartupDataInner::Cpp(t) => *t,
72 StartupDataInner::Cow(c) => RawStartupData {
73 data: c.as_ptr() as _,
74 raw_size: c.len() as _,
75 },
76 };
77 unsafe { v8__StartupData__CanBeRehashed(&tmp) }
78 }
79
80 pub fn is_valid(&self) -> bool {
83 let tmp = match &self.0 {
84 StartupDataInner::Cpp(t) => *t,
85 StartupDataInner::Cow(c) => RawStartupData {
86 data: c.as_ptr() as _,
87 raw_size: c.len() as _,
88 },
89 };
90 unsafe { v8__StartupData__IsValid(&tmp) }
91 }
92}
93
94impl std::ops::Deref for StartupData {
95 type Target = [u8];
96
97 fn deref(&self) -> &Self::Target {
98 match &self.0 {
99 StartupDataInner::Cpp(t) => unsafe {
100 std::slice::from_raw_parts(t.data as _, t.raw_size as _)
101 },
102 StartupDataInner::Cow(c) => c,
103 }
104 }
105}
106
107impl<T> From<T> for StartupData
108where
109 T: Into<Cow<'static, [u8]>>,
110{
111 fn from(value: T) -> Self {
112 Self(StartupDataInner::Cow(value.into()))
113 }
114}
115
116impl Drop for StartupData {
117 fn drop(&mut self) {
118 if let StartupDataInner::Cpp(raw) = self.0 {
119 unsafe {
120 v8__StartupData__data__DELETE(raw.data);
121 }
122 }
123 }
124}
125
126impl Clone for StartupDataInner {
127 fn clone(&self) -> Self {
128 match self {
129 Self::Cpp(r) => Self::Cow(
131 unsafe { std::slice::from_raw_parts(r.data as _, r.raw_size as _) }
132 .to_vec()
133 .into(),
134 ),
135 Self::Cow(c) => Self::Cow(c.clone()),
136 }
137 }
138}
139
140#[repr(C)]
141#[derive(Debug)]
142pub enum FunctionCodeHandling {
143 Clear,
144 Keep,
145}
146
147#[repr(C)]
149#[derive(Debug)]
150pub(crate) struct SnapshotCreator([usize; 1]);
151
152impl SnapshotCreator {
153 #[inline(always)]
156 #[allow(clippy::new_ret_no_self)]
157 pub(crate) fn new(
158 external_references: Option<Cow<'static, [ExternalReference]>>,
159 params: Option<crate::CreateParams>,
160 ) -> OwnedIsolate {
161 Self::new_impl(external_references, None, params)
162 }
163
164 #[inline(always)]
167 #[allow(clippy::new_ret_no_self)]
168 pub(crate) fn from_existing_snapshot(
169 existing_snapshot_blob: StartupData,
170 external_references: Option<Cow<'static, [ExternalReference]>>,
171 params: Option<crate::CreateParams>,
172 ) -> OwnedIsolate {
173 Self::new_impl(external_references, Some(existing_snapshot_blob), params)
174 }
175
176 #[inline(always)]
179 #[allow(clippy::new_ret_no_self)]
180 fn new_impl(
181 external_references: Option<Cow<'static, [ExternalReference]>>,
182 existing_snapshot_blob: Option<StartupData>,
183 params: Option<crate::CreateParams>,
184 ) -> OwnedIsolate {
185 let mut snapshot_creator: MaybeUninit<Self> = MaybeUninit::uninit();
186
187 let mut params = params.unwrap_or_default();
188 if let Some(external_refs) = external_references {
189 params = params.external_references(external_refs);
190 }
191 if let Some(snapshot_blob) = existing_snapshot_blob {
192 params = params.snapshot_blob(snapshot_blob);
193 }
194 let (raw_create_params, create_param_allocations) = params.finalize();
195
196 let snapshot_creator = unsafe {
197 v8__SnapshotCreator__CONSTRUCT(&mut snapshot_creator, &raw_create_params);
198 snapshot_creator.assume_init()
199 };
200
201 let isolate_ptr =
202 unsafe { v8__SnapshotCreator__GetIsolate(&snapshot_creator) };
203 let mut owned_isolate = OwnedIsolate::new_already_entered(isolate_ptr);
204 owned_isolate.initialize(create_param_allocations);
205 owned_isolate.set_snapshot_creator(snapshot_creator);
206 owned_isolate
207 }
208}
209
210impl Drop for SnapshotCreator {
211 fn drop(&mut self) {
212 unsafe { v8__SnapshotCreator__DESTRUCT(self) };
213 }
214}
215
216impl SnapshotCreator {
217 #[inline(always)]
221 pub(crate) fn set_default_context(&mut self, context: Local<Context>) {
222 unsafe { v8__SnapshotCreator__SetDefaultContext(self, &*context) };
223 }
224
225 #[inline(always)]
230 pub(crate) fn add_context(&mut self, context: Local<Context>) -> usize {
231 unsafe { v8__SnapshotCreator__AddContext(self, &*context) }
232 }
233
234 #[inline(always)]
239 pub(crate) fn add_isolate_data<T>(&mut self, data: Local<T>) -> usize
240 where
241 for<'l> Local<'l, T>: Into<Local<'l, Data>>,
242 {
243 unsafe { v8__SnapshotCreator__AddData_to_isolate(self, &*data.into()) }
244 }
245
246 #[inline(always)]
251 pub(crate) fn add_context_data<T>(
252 &mut self,
253 context: Local<Context>,
254 data: Local<T>,
255 ) -> usize
256 where
257 for<'l> Local<'l, T>: Into<Local<'l, Data>>,
258 {
259 unsafe {
260 v8__SnapshotCreator__AddData_to_context(self, &*context, &*data.into())
261 }
262 }
263
264 #[inline(always)]
267 pub(crate) fn create_blob(
268 &mut self,
269 function_code_handling: FunctionCodeHandling,
270 ) -> Option<StartupData> {
271 let blob =
272 unsafe { v8__SnapshotCreator__CreateBlob(self, function_code_handling) };
273 if blob.data.is_null() {
274 debug_assert!(blob.raw_size == 0);
275 None
276 } else {
277 debug_assert!(blob.raw_size > 0);
278 Some(StartupData(StartupDataInner::Cpp(blob)))
279 }
280 }
281}