use anyhow::Result;
use deno_broadcast_channel::InMemoryBroadcastChannel;
use deno_core::{Extension, JsRuntime, RuntimeOptions};
use deno_web::BlobStore;
use std::{env, path::PathBuf};
use crate::permissions::Permissions;
const JS_PATHS: &[&str] = &["js/**/*.js"];
pub fn create_snapshot_with_main_module(
exts: Vec<Extension>,
files: &[PathBuf],
code: Option<String>,
) -> Result<Vec<u8>> {
_create_snapshot(exts, files, code, false)
}
pub fn create_snapshot(exts: Vec<Extension>, files: &[PathBuf]) -> Result<Vec<u8>> {
_create_snapshot(exts, files, None, true)
}
pub fn _create_snapshot(
exts: Vec<Extension>,
files: &[PathBuf],
code: Option<String>,
build: bool,
) -> Result<Vec<u8>> {
let mut extensions = vec![
deno_webidl::init(),
deno_console::init(),
deno_url::init(),
deno_web::init::<Permissions>(BlobStore::default(), Default::default()),
deno_fetch::init::<Permissions>(Default::default()),
deno_websocket::init::<Permissions>("".to_owned(), None, None),
deno_webstorage::init(None),
deno_crypto::init(None),
deno_webgpu::init(false),
deno_broadcast_channel::init(InMemoryBroadcastChannel::default(), false),
deno_tls::init(),
deno_ffi::init::<Permissions>(false),
deno_net::init::<Permissions>(
None, false, None,
),
deno_http::init(),
];
extensions.extend(exts);
let rt = JsRuntime::new(RuntimeOptions {
will_snapshot: true,
extensions,
..Default::default()
});
_gen_snapshot(rt, files, code, build)
}
pub fn get_js_files(base_dir: &str, paths: &[&str]) -> Vec<PathBuf> {
let mut files: Vec<_> = paths
.iter()
.flat_map(|p| {
glob::glob(format!("{}/{}", base_dir, p).as_str())
.unwrap()
.filter_map(Result::ok)
.collect::<Vec<_>>()
})
.collect();
files.sort();
files
}
fn _gen_snapshot(
mut rt: JsRuntime,
files: &[PathBuf],
code: Option<String>,
build: bool,
) -> Result<Vec<u8>> {
let base_dir = env!("CARGO_MANIFEST_DIR");
let mut all_files = get_js_files(base_dir, JS_PATHS);
all_files.extend_from_slice(files);
for file in all_files {
if build {
println!("cargo:rerun-if-changed={}", file.display());
}
let display_path_str = file.display().to_string();
rt.execute_script(
&("deno:".to_string() + &display_path_str.replace('\\', "/")),
&std::fs::read_to_string(&file).unwrap(),
)?;
}
if let Some(v) = code {
rt.execute_script("deno:main", &v)?;
}
let snapshot = rt.snapshot();
let snapshot_slice: &[u8] = &*snapshot;
Ok(zstd::encode_all(snapshot_slice, 7)?)
}