1use crate::ops;
4use crate::ops::bootstrap::SnapshotOptions;
5use crate::shared::maybe_transpile_source;
6use crate::shared::runtime;
7use deno_cache::SqliteBackedCache;
8use deno_core::snapshot::*;
9use deno_core::v8;
10use deno_core::Extension;
11use deno_http::DefaultHttpPropertyExtractor;
12use deno_io::fs::FsError;
13use deno_permissions::PermissionCheckError;
14use std::borrow::Cow;
15use std::io::Write;
16use std::path::Path;
17use std::path::PathBuf;
18use std::rc::Rc;
19use std::sync::Arc;
20
21#[derive(Clone)]
22struct Permissions;
23
24impl deno_websocket::WebSocketPermissions for Permissions {
25 fn check_net_url(
26 &mut self,
27 _url: &deno_core::url::Url,
28 _api_name: &str,
29 ) -> Result<(), PermissionCheckError> {
30 unreachable!("snapshotting!")
31 }
32}
33
34impl deno_web::TimersPermission for Permissions {
35 fn allow_hrtime(&mut self) -> bool {
36 unreachable!("snapshotting!")
37 }
38}
39
40impl deno_fetch::FetchPermissions for Permissions {
41 fn check_net_url(
42 &mut self,
43 _url: &deno_core::url::Url,
44 _api_name: &str,
45 ) -> Result<(), PermissionCheckError> {
46 unreachable!("snapshotting!")
47 }
48
49 fn check_read<'a>(
50 &mut self,
51 _p: &'a Path,
52 _api_name: &str,
53 ) -> Result<Cow<'a, Path>, PermissionCheckError> {
54 unreachable!("snapshotting!")
55 }
56}
57
58impl deno_ffi::FfiPermissions for Permissions {
59 fn check_partial_no_path(&mut self) -> Result<(), PermissionCheckError> {
60 unreachable!("snapshotting!")
61 }
62
63 fn check_partial_with_path(
64 &mut self,
65 _path: &str,
66 ) -> Result<PathBuf, PermissionCheckError> {
67 unreachable!("snapshotting!")
68 }
69}
70
71impl deno_napi::NapiPermissions for Permissions {
72 fn check(&mut self, _path: &str) -> Result<PathBuf, PermissionCheckError> {
73 unreachable!("snapshotting!")
74 }
75}
76
77impl deno_node::NodePermissions for Permissions {
78 fn check_net_url(
79 &mut self,
80 _url: &deno_core::url::Url,
81 _api_name: &str,
82 ) -> Result<(), PermissionCheckError> {
83 unreachable!("snapshotting!")
84 }
85 fn check_net(
86 &mut self,
87 _host: (&str, Option<u16>),
88 _api_name: &str,
89 ) -> Result<(), PermissionCheckError> {
90 unreachable!("snapshotting!")
91 }
92 fn check_read_path<'a>(
93 &mut self,
94 _path: &'a Path,
95 ) -> Result<Cow<'a, Path>, PermissionCheckError> {
96 unreachable!("snapshotting!")
97 }
98 fn check_read_with_api_name(
99 &mut self,
100 _p: &str,
101 _api_name: Option<&str>,
102 ) -> Result<PathBuf, PermissionCheckError> {
103 unreachable!("snapshotting!")
104 }
105 fn query_read_all(&mut self) -> bool {
106 unreachable!("snapshotting!")
107 }
108 fn check_write_with_api_name(
109 &mut self,
110 _p: &str,
111 _api_name: Option<&str>,
112 ) -> Result<PathBuf, PermissionCheckError> {
113 unreachable!("snapshotting!")
114 }
115 fn check_sys(
116 &mut self,
117 _kind: &str,
118 _api_name: &str,
119 ) -> Result<(), PermissionCheckError> {
120 unreachable!("snapshotting!")
121 }
122}
123
124impl deno_net::NetPermissions for Permissions {
125 fn check_net<T: AsRef<str>>(
126 &mut self,
127 _host: &(T, Option<u16>),
128 _api_name: &str,
129 ) -> Result<(), PermissionCheckError> {
130 unreachable!("snapshotting!")
131 }
132
133 fn check_read(
134 &mut self,
135 _p: &str,
136 _api_name: &str,
137 ) -> Result<PathBuf, PermissionCheckError> {
138 unreachable!("snapshotting!")
139 }
140
141 fn check_write(
142 &mut self,
143 _p: &str,
144 _api_name: &str,
145 ) -> Result<PathBuf, PermissionCheckError> {
146 unreachable!("snapshotting!")
147 }
148
149 fn check_write_path<'a>(
150 &mut self,
151 _p: &'a Path,
152 _api_name: &str,
153 ) -> Result<Cow<'a, Path>, PermissionCheckError> {
154 unreachable!("snapshotting!")
155 }
156}
157
158impl deno_fs::FsPermissions for Permissions {
159 fn check_open<'a>(
160 &mut self,
161 _resolved: bool,
162 _read: bool,
163 _write: bool,
164 _path: &'a Path,
165 _api_name: &str,
166 ) -> Result<Cow<'a, Path>, FsError> {
167 unreachable!("snapshotting!")
168 }
169
170 fn check_read(
171 &mut self,
172 _path: &str,
173 _api_name: &str,
174 ) -> Result<PathBuf, PermissionCheckError> {
175 unreachable!("snapshotting!")
176 }
177
178 fn check_read_all(
179 &mut self,
180 _api_name: &str,
181 ) -> Result<(), PermissionCheckError> {
182 unreachable!("snapshotting!")
183 }
184
185 fn check_read_blind(
186 &mut self,
187 _path: &Path,
188 _display: &str,
189 _api_name: &str,
190 ) -> Result<(), PermissionCheckError> {
191 unreachable!("snapshotting!")
192 }
193
194 fn check_write(
195 &mut self,
196 _path: &str,
197 _api_name: &str,
198 ) -> Result<PathBuf, PermissionCheckError> {
199 unreachable!("snapshotting!")
200 }
201
202 fn check_write_partial(
203 &mut self,
204 _path: &str,
205 _api_name: &str,
206 ) -> Result<PathBuf, PermissionCheckError> {
207 unreachable!("snapshotting!")
208 }
209
210 fn check_write_all(
211 &mut self,
212 _api_name: &str,
213 ) -> Result<(), PermissionCheckError> {
214 unreachable!("snapshotting!")
215 }
216
217 fn check_write_blind(
218 &mut self,
219 _path: &Path,
220 _display: &str,
221 _api_name: &str,
222 ) -> Result<(), PermissionCheckError> {
223 unreachable!("snapshotting!")
224 }
225
226 fn check_read_path<'a>(
227 &mut self,
228 _path: &'a Path,
229 _api_name: &str,
230 ) -> Result<Cow<'a, Path>, PermissionCheckError> {
231 unreachable!("snapshotting!")
232 }
233
234 fn check_write_path<'a>(
235 &mut self,
236 _path: &'a Path,
237 _api_name: &str,
238 ) -> Result<Cow<'a, Path>, PermissionCheckError> {
239 unreachable!("snapshotting!")
240 }
241}
242
243impl deno_kv::sqlite::SqliteDbHandlerPermissions for Permissions {
244 fn check_read(
245 &mut self,
246 _path: &str,
247 _api_name: &str,
248 ) -> Result<PathBuf, PermissionCheckError> {
249 unreachable!("snapshotting!")
250 }
251
252 fn check_write<'a>(
253 &mut self,
254 _path: &'a Path,
255 _api_name: &str,
256 ) -> Result<Cow<'a, Path>, PermissionCheckError> {
257 unreachable!("snapshotting!")
258 }
259}
260
261pub fn create_runtime_snapshot(
262 snapshot_path: PathBuf,
263 snapshot_options: SnapshotOptions,
264 custom_extensions: Vec<Extension>,
266) {
267 let fs = std::sync::Arc::new(deno_fs::RealFs);
270 let mut extensions: Vec<Extension> = vec![
271 deno_telemetry::deno_telemetry::init_ops_and_esm(),
272 deno_webidl::deno_webidl::init_ops_and_esm(),
273 deno_console::deno_console::init_ops_and_esm(),
274 deno_url::deno_url::init_ops_and_esm(),
275 deno_web::deno_web::init_ops_and_esm::<Permissions>(
276 Default::default(),
277 Default::default(),
278 ),
279 deno_webgpu::deno_webgpu::init_ops_and_esm(),
280 deno_canvas::deno_canvas::init_ops_and_esm(),
281 deno_fetch::deno_fetch::init_ops_and_esm::<Permissions>(Default::default()),
282 deno_cache::deno_cache::init_ops_and_esm::<SqliteBackedCache>(None),
283 deno_websocket::deno_websocket::init_ops_and_esm::<Permissions>(
284 "".to_owned(),
285 None,
286 None,
287 ),
288 deno_webstorage::deno_webstorage::init_ops_and_esm(None),
289 deno_crypto::deno_crypto::init_ops_and_esm(None),
290 deno_broadcast_channel::deno_broadcast_channel::init_ops_and_esm(
291 deno_broadcast_channel::InMemoryBroadcastChannel::default(),
292 ),
293 deno_ffi::deno_ffi::init_ops_and_esm::<Permissions>(),
294 deno_net::deno_net::init_ops_and_esm::<Permissions>(None, None),
295 deno_tls::deno_tls::init_ops_and_esm(),
296 deno_kv::deno_kv::init_ops_and_esm(
297 deno_kv::sqlite::SqliteDbHandler::<Permissions>::new(None, None),
298 deno_kv::KvConfig::builder().build(),
299 ),
300 deno_cron::deno_cron::init_ops_and_esm(
301 deno_cron::local::LocalCronHandler::new(),
302 ),
303 deno_napi::deno_napi::init_ops_and_esm::<Permissions>(),
304 deno_http::deno_http::init_ops_and_esm::<DefaultHttpPropertyExtractor>(
305 deno_http::Options::default(),
306 ),
307 deno_io::deno_io::init_ops_and_esm(Default::default()),
308 deno_fs::deno_fs::init_ops_and_esm::<Permissions>(fs.clone()),
309 deno_node::deno_node::init_ops_and_esm::<Permissions>(None, fs.clone()),
310 runtime::init_ops_and_esm(),
311 ops::runtime::deno_runtime::init_ops("deno:runtime".parse().unwrap()),
312 ops::worker_host::deno_worker_host::init_ops(
313 Arc::new(|_| unreachable!("not used in snapshot.")),
314 None,
315 ),
316 ops::fs_events::deno_fs_events::init_ops(),
317 ops::os::deno_os::init_ops(Default::default()),
318 ops::permissions::deno_permissions::init_ops(),
319 ops::process::deno_process::init_ops(None),
320 ops::signal::deno_signal::init_ops(),
321 ops::tty::deno_tty::init_ops(),
322 ops::http::deno_http_runtime::init_ops(),
323 ops::bootstrap::deno_bootstrap::init_ops(Some(snapshot_options)),
324 ops::web_worker::deno_web_worker::init_ops(),
325 ];
326 extensions.extend(custom_extensions);
327
328 let output = create_snapshot(
329 CreateSnapshotOptions {
330 cargo_manifest_dir: env!("CARGO_MANIFEST_DIR"),
331 startup_snapshot: None,
332 extensions,
333 extension_transpiler: Some(Rc::new(|specifier, source| {
334 maybe_transpile_source(specifier, source)
335 })),
336 with_runtime_cb: Some(Box::new(|rt| {
337 let isolate = rt.v8_isolate();
338 let scope = &mut v8::HandleScope::new(isolate);
339
340 let tmpl = deno_node::init_global_template(
341 scope,
342 deno_node::ContextInitMode::ForSnapshot,
343 );
344 let ctx = deno_node::create_v8_context(
345 scope,
346 tmpl,
347 deno_node::ContextInitMode::ForSnapshot,
348 std::ptr::null_mut(),
349 );
350 assert_eq!(scope.add_context(ctx), deno_node::VM_CONTEXT_INDEX);
351 })),
352 skip_op_registration: false,
353 },
354 None,
355 )
356 .unwrap();
357 let mut snapshot = std::fs::File::create(snapshot_path).unwrap();
358 snapshot.write_all(&output.output).unwrap();
359
360 #[allow(clippy::print_stdout)]
361 for path in output.files_loaded_during_snapshot {
362 println!("cargo:rerun-if-changed={}", path.display());
363 }
364}