diff options
Diffstat (limited to 'cli/build.rs')
-rw-r--r-- | cli/build.rs | 295 |
1 files changed, 153 insertions, 142 deletions
diff --git a/cli/build.rs b/cli/build.rs index 216969e39..e4df856f7 100644 --- a/cli/build.rs +++ b/cli/build.rs @@ -1,11 +1,13 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. +use std::cell::RefCell; use std::env; use std::path::PathBuf; +use std::rc::Rc; -use deno_core::include_js_files; use deno_core::snapshot_util::*; use deno_core::Extension; +use deno_core::ExtensionBuilder; use deno_core::ExtensionFileSource; use deno_core::ExtensionFileSourceCode; use deno_runtime::deno_cache::SqliteBackedCache; @@ -33,6 +35,105 @@ mod ts { specifier: String, } + #[op] + fn op_build_info(state: &mut OpState) -> Value { + let build_specifier = "asset:///bootstrap.ts"; + + let node_built_in_module_names = SUPPORTED_BUILTIN_NODE_MODULES + .iter() + .map(|s| s.name) + .collect::<Vec<&str>>(); + let build_libs = state.borrow::<Vec<&str>>(); + json!({ + "buildSpecifier": build_specifier, + "libs": build_libs, + "nodeBuiltInModuleNames": node_built_in_module_names, + }) + } + + #[op] + fn op_is_node_file() -> bool { + false + } + + #[op] + fn op_script_version( + _state: &mut OpState, + _args: Value, + ) -> Result<Option<String>, AnyError> { + Ok(Some("1".to_string())) + } + + #[op] + // using the same op that is used in `tsc.rs` for loading modules and reading + // files, but a slightly different implementation at build time. + fn op_load(state: &mut OpState, args: LoadArgs) -> Result<Value, AnyError> { + let op_crate_libs = state.borrow::<HashMap<&str, PathBuf>>(); + let path_dts = state.borrow::<PathBuf>(); + let re_asset = + Regex::new(r"asset:/{3}lib\.(\S+)\.d\.ts").expect("bad regex"); + let build_specifier = "asset:///bootstrap.ts"; + + // we need a basic file to send to tsc to warm it up. + if args.specifier == build_specifier { + Ok(json!({ + "data": r#"Deno.writeTextFile("hello.txt", "hello deno!");"#, + "version": "1", + // this corresponds to `ts.ScriptKind.TypeScript` + "scriptKind": 3 + })) + // specifiers come across as `asset:///lib.{lib_name}.d.ts` and we need to + // parse out just the name so we can lookup the asset. + } else if let Some(caps) = re_asset.captures(&args.specifier) { + if let Some(lib) = caps.get(1).map(|m| m.as_str()) { + // if it comes from an op crate, we were supplied with the path to the + // file. + let path = if let Some(op_crate_lib) = op_crate_libs.get(lib) { + PathBuf::from(op_crate_lib).canonicalize()? + // otherwise we will generate the path ourself + } else { + path_dts.join(format!("lib.{lib}.d.ts")) + }; + let data = std::fs::read_to_string(path)?; + Ok(json!({ + "data": data, + "version": "1", + // this corresponds to `ts.ScriptKind.TypeScript` + "scriptKind": 3 + })) + } else { + Err(custom_error( + "InvalidSpecifier", + format!("An invalid specifier was requested: {}", args.specifier), + )) + } + } else { + Err(custom_error( + "InvalidSpecifier", + format!("An invalid specifier was requested: {}", args.specifier), + )) + } + } + + deno_core::extension!(deno_tsc, + ops = [op_build_info, op_is_node_file, op_load, op_script_version], + js = [ + dir "tsc", + "00_typescript.js", + "99_main_compiler.js", + ], + config = { + op_crate_libs: HashMap<&'static str, PathBuf>, + build_libs: Vec<&'static str>, + path_dts: PathBuf, + }, + state = |state, op_crate_libs, build_libs, path_dts| { + state.put(op_crate_libs); + state.put(build_libs); + state.put(path_dts); + }, + ); + pub fn create_compiler_snapshot(snapshot_path: PathBuf, cwd: &Path) { // libs that are being provided by op crates. let mut op_crate_libs = HashMap::new(); @@ -158,110 +259,15 @@ mod ts { ) .unwrap(); - #[op] - fn op_build_info(state: &mut OpState) -> Value { - let build_specifier = "asset:///bootstrap.ts"; - - let node_built_in_module_names = SUPPORTED_BUILTIN_NODE_MODULES - .iter() - .map(|s| s.name) - .collect::<Vec<&str>>(); - let build_libs = state.borrow::<Vec<&str>>(); - json!({ - "buildSpecifier": build_specifier, - "libs": build_libs, - "nodeBuiltInModuleNames": node_built_in_module_names, - }) - } - - #[op] - fn op_is_node_file() -> bool { - false - } - - #[op] - fn op_script_version( - _state: &mut OpState, - _args: Value, - ) -> Result<Option<String>, AnyError> { - Ok(Some("1".to_string())) - } - - #[op] - // using the same op that is used in `tsc.rs` for loading modules and reading - // files, but a slightly different implementation at build time. - fn op_load(state: &mut OpState, args: LoadArgs) -> Result<Value, AnyError> { - let op_crate_libs = state.borrow::<HashMap<&str, PathBuf>>(); - let path_dts = state.borrow::<PathBuf>(); - let re_asset = - Regex::new(r"asset:/{3}lib\.(\S+)\.d\.ts").expect("bad regex"); - let build_specifier = "asset:///bootstrap.ts"; - - // we need a basic file to send to tsc to warm it up. - if args.specifier == build_specifier { - Ok(json!({ - "data": r#"Deno.writeTextFile("hello.txt", "hello deno!");"#, - "version": "1", - // this corresponds to `ts.ScriptKind.TypeScript` - "scriptKind": 3 - })) - // specifiers come across as `asset:///lib.{lib_name}.d.ts` and we need to - // parse out just the name so we can lookup the asset. - } else if let Some(caps) = re_asset.captures(&args.specifier) { - if let Some(lib) = caps.get(1).map(|m| m.as_str()) { - // if it comes from an op crate, we were supplied with the path to the - // file. - let path = if let Some(op_crate_lib) = op_crate_libs.get(lib) { - PathBuf::from(op_crate_lib).canonicalize()? - // otherwise we are will generate the path ourself - } else { - path_dts.join(format!("lib.{lib}.d.ts")) - }; - let data = std::fs::read_to_string(path)?; - Ok(json!({ - "data": data, - "version": "1", - // this corresponds to `ts.ScriptKind.TypeScript` - "scriptKind": 3 - })) - } else { - Err(custom_error( - "InvalidSpecifier", - format!("An invalid specifier was requested: {}", args.specifier), - )) - } - } else { - Err(custom_error( - "InvalidSpecifier", - format!("An invalid specifier was requested: {}", args.specifier), - )) - } - } - - let tsc_extension = Extension::builder("deno_tsc") - .ops(vec![ - op_build_info::decl(), - op_is_node_file::decl(), - op_load::decl(), - op_script_version::decl(), - ]) - .js(include_js_files! { - dir "tsc", - "00_typescript.js", - "99_main_compiler.js", - }) - .state(move |state| { - state.put(op_crate_libs.clone()); - state.put(build_libs.clone()); - state.put(path_dts.clone()); - }) - .build(); - create_snapshot(CreateSnapshotOptions { cargo_manifest_dir: env!("CARGO_MANIFEST_DIR"), snapshot_path, startup_snapshot: None, - extensions: vec![tsc_extension], + extensions: vec![deno_tsc::init_ops_and_esm( + op_crate_libs, + build_libs, + path_dts, + )], // NOTE(bartlomieju): Compressing the TSC snapshot in debug build took // ~45s on M1 MacBook Pro; without compression it took ~1s. @@ -304,61 +310,66 @@ mod ts { } } +// FIXME(bartlomieju): information about which extensions were +// already snapshotted is not preserved in the snapshot. This should be +// fixed, so we can reliably depend on that information. +// deps = [runtime] +deno_core::extension!( + cli, + esm = [ + dir "js", + "40_testing.js" + ], + customizer = |ext: &mut ExtensionBuilder| { + ext.esm(vec![ExtensionFileSource { + specifier: "runtime/js/99_main.js".to_string(), + code: ExtensionFileSourceCode::LoadedFromFsDuringSnapshot( + std::path::PathBuf::from(deno_runtime::js::PATH_FOR_99_MAIN_JS), + ), + }]); + } +); + fn create_cli_snapshot(snapshot_path: PathBuf) { // NOTE(bartlomieju): ordering is important here, keep it in sync with // `runtime/worker.rs`, `runtime/web_worker.rs` and `runtime/build.rs`! - let mut extensions: Vec<Extension> = vec![ - deno_webidl::init(), - deno_console::init(), - deno_url::init_ops(), - deno_web::init_ops::<PermissionsContainer>( + let extensions: Vec<Extension> = vec![ + deno_webidl::deno_webidl::init_ops(), + deno_console::deno_console::init_ops(), + deno_url::deno_url::init_ops(), + deno_web::deno_web::init_ops::<PermissionsContainer>( deno_web::BlobStore::default(), Default::default(), ), - deno_fetch::init_ops::<PermissionsContainer>(Default::default()), - deno_cache::init_ops::<SqliteBackedCache>(None), - deno_websocket::init_ops::<PermissionsContainer>("".to_owned(), None, None), - deno_webstorage::init_ops(None), - deno_crypto::init_ops(None), - deno_broadcast_channel::init_ops( + deno_fetch::deno_fetch::init_ops::<PermissionsContainer>(Default::default()), + deno_cache::deno_cache::init_ops::<SqliteBackedCache>(None), + deno_websocket::deno_websocket::init_ops::<PermissionsContainer>( + "".to_owned(), + None, + None, + ), + deno_webstorage::deno_webstorage::init_ops(None), + deno_crypto::deno_crypto::init_ops(None), + deno_broadcast_channel::deno_broadcast_channel::init_ops( deno_broadcast_channel::InMemoryBroadcastChannel::default(), false, // No --unstable. ), - deno_ffi::init_ops::<PermissionsContainer>(false), - deno_net::init_ops::<PermissionsContainer>( + deno_ffi::deno_ffi::init_ops::<PermissionsContainer>(false), + deno_net::deno_net::init_ops::<PermissionsContainer>( None, false, // No --unstable. None, ), - deno_tls::init_ops(), - deno_napi::init_ops::<PermissionsContainer>(), - deno_http::init_ops(), - deno_io::init_ops(Default::default()), - deno_fs::init_ops::<PermissionsContainer>(false), - deno_flash::init_ops::<PermissionsContainer>(false), // No --unstable - deno_node::init_ops::<PermissionsContainer>(None), // No --unstable. - deno_node::init_polyfill_ops(), + deno_tls::deno_tls::init_ops(), + deno_napi::deno_napi::init_ops::<PermissionsContainer>(), + deno_http::deno_http::init_ops(), + deno_io::deno_io::init_ops(Rc::new(RefCell::new(Some(Default::default())))), + deno_fs::deno_fs::init_ops::<PermissionsContainer>(false), + deno_flash::deno_flash::init_ops::<PermissionsContainer>(false), // No --unstable + deno_node::deno_node_loading::init_ops::<PermissionsContainer>(None), // No --unstable. + deno_node::deno_node::init_ops(), + cli::init_ops_and_esm(), // NOTE: This needs to be init_ops_and_esm! ]; - let mut esm_files = include_js_files!( - dir "js", - "40_testing.js", - ); - esm_files.push(ExtensionFileSource { - specifier: "runtime/js/99_main.js".to_string(), - code: ExtensionFileSourceCode::LoadedFromFsDuringSnapshot( - std::path::PathBuf::from(deno_runtime::js::PATH_FOR_99_MAIN_JS), - ), - }); - extensions.push( - Extension::builder("cli") - // FIXME(bartlomieju): information about which extensions were - // already snapshotted is not preserved in the snapshot. This should be - // fixed, so we can reliably depend on that information. - // .dependencies(vec!["runtime"]) - .esm(esm_files) - .build(), - ); - create_snapshot(CreateSnapshotOptions { cargo_manifest_dir: env!("CARGO_MANIFEST_DIR"), snapshot_path, |