diff options
-rw-r--r-- | Cargo.lock | 48 | ||||
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | cli/Cargo.toml | 11 | ||||
-rw-r--r-- | cli/build.rs | 17 | ||||
-rw-r--r-- | cli/errors.rs | 195 | ||||
-rw-r--r-- | cli/file_fetcher.rs | 4 | ||||
-rw-r--r-- | cli/file_watcher.rs | 13 | ||||
-rw-r--r-- | cli/http_util.rs | 20 | ||||
-rw-r--r-- | cli/js.rs | 27 | ||||
-rw-r--r-- | cli/main.rs | 53 | ||||
-rw-r--r-- | cli/module_loader.rs | 2 | ||||
-rw-r--r-- | cli/ops/mod.rs | 56 | ||||
-rw-r--r-- | cli/ops/runtime_compiler.rs | 8 | ||||
-rw-r--r-- | cli/program_state.rs | 4 | ||||
-rw-r--r-- | cli/signal.rs | 62 | ||||
-rw-r--r-- | cli/specifier_handler.rs | 2 | ||||
-rw-r--r-- | cli/standalone.rs | 7 | ||||
-rw-r--r-- | cli/tools/coverage.rs | 2 | ||||
-rw-r--r-- | cli/tools/repl.rs | 4 | ||||
-rw-r--r-- | cli/tools/upgrade.rs | 4 | ||||
-rw-r--r-- | core/error.rs | 5 | ||||
-rw-r--r-- | runtime/Cargo.toml | 74 | ||||
-rw-r--r-- | runtime/README.md | 44 | ||||
-rw-r--r-- | runtime/build.rs | 81 | ||||
-rw-r--r-- | runtime/colors.rs | 130 | ||||
-rw-r--r-- | runtime/errors.rs | 209 | ||||
-rw-r--r-- | runtime/examples/hello_runtime.js | 2 | ||||
-rw-r--r-- | runtime/examples/hello_runtime.rs | 55 | ||||
-rw-r--r-- | runtime/fs_util.rs | 80 | ||||
-rw-r--r-- | runtime/http_util.rs | 46 | ||||
-rw-r--r-- | runtime/inspector.rs (renamed from cli/inspector.rs) | 0 | ||||
-rw-r--r-- | runtime/js.rs | 31 | ||||
-rw-r--r-- | runtime/lib.rs | 26 | ||||
-rw-r--r-- | runtime/metrics.rs (renamed from cli/metrics.rs) | 0 | ||||
-rw-r--r-- | runtime/ops/crypto.rs (renamed from cli/ops/crypto.rs) | 0 | ||||
-rw-r--r-- | runtime/ops/dispatch_minimal.rs (renamed from cli/ops/dispatch_minimal.rs) | 0 | ||||
-rw-r--r-- | runtime/ops/fetch.rs (renamed from cli/ops/fetch.rs) | 9 | ||||
-rw-r--r-- | runtime/ops/fs.rs (renamed from cli/ops/fs.rs) | 0 | ||||
-rw-r--r-- | runtime/ops/fs_events.rs (renamed from cli/ops/fs_events.rs) | 0 | ||||
-rw-r--r-- | runtime/ops/io.rs (renamed from cli/ops/io.rs) | 0 | ||||
-rw-r--r-- | runtime/ops/mod.rs | 89 | ||||
-rw-r--r-- | runtime/ops/net.rs (renamed from cli/ops/net.rs) | 0 | ||||
-rw-r--r-- | runtime/ops/net_unix.rs (renamed from cli/ops/net_unix.rs) | 0 | ||||
-rw-r--r-- | runtime/ops/os.rs (renamed from cli/ops/os.rs) | 0 | ||||
-rw-r--r-- | runtime/ops/permissions.rs (renamed from cli/ops/permissions.rs) | 0 | ||||
-rw-r--r-- | runtime/ops/plugin.rs (renamed from cli/ops/plugin.rs) | 0 | ||||
-rw-r--r-- | runtime/ops/process.rs (renamed from cli/ops/process.rs) | 56 | ||||
-rw-r--r-- | runtime/ops/runtime.rs (renamed from cli/ops/runtime.rs) | 0 | ||||
-rw-r--r-- | runtime/ops/signal.rs (renamed from cli/ops/signal.rs) | 0 | ||||
-rw-r--r-- | runtime/ops/timers.rs (renamed from cli/ops/timers.rs) | 0 | ||||
-rw-r--r-- | runtime/ops/tls.rs (renamed from cli/ops/tls.rs) | 0 | ||||
-rw-r--r-- | runtime/ops/tty.rs (renamed from cli/ops/tty.rs) | 14 | ||||
-rw-r--r-- | runtime/ops/web_worker.rs (renamed from cli/ops/web_worker.rs) | 0 | ||||
-rw-r--r-- | runtime/ops/websocket.rs (renamed from cli/ops/websocket.rs) | 0 | ||||
-rw-r--r-- | runtime/ops/worker_host.rs (renamed from cli/ops/worker_host.rs) | 0 | ||||
-rw-r--r-- | runtime/permissions.rs (renamed from cli/permissions.rs) | 43 | ||||
-rw-r--r-- | runtime/resolve_addr.rs (renamed from cli/resolve_addr.rs) | 0 | ||||
-rw-r--r-- | runtime/rt/00_bootstrap_namespace.js (renamed from cli/rt/00_bootstrap_namespace.js) | 0 | ||||
-rw-r--r-- | runtime/rt/01_build.js (renamed from cli/rt/01_build.js) | 0 | ||||
-rw-r--r-- | runtime/rt/01_colors.js (renamed from cli/rt/01_colors.js) | 0 | ||||
-rw-r--r-- | runtime/rt/01_errors.js (renamed from cli/rt/01_errors.js) | 0 | ||||
-rw-r--r-- | runtime/rt/01_internals.js (renamed from cli/rt/01_internals.js) | 0 | ||||
-rw-r--r-- | runtime/rt/01_version.js (renamed from cli/rt/01_version.js) | 0 | ||||
-rw-r--r-- | runtime/rt/01_web_util.js (renamed from cli/rt/01_web_util.js) | 0 | ||||
-rw-r--r-- | runtime/rt/02_console.js (renamed from cli/rt/02_console.js) | 0 | ||||
-rw-r--r-- | runtime/rt/06_util.js (renamed from cli/rt/06_util.js) | 0 | ||||
-rw-r--r-- | runtime/rt/10_dispatch_minimal.js (renamed from cli/rt/10_dispatch_minimal.js) | 0 | ||||
-rw-r--r-- | runtime/rt/11_timers.js (renamed from cli/rt/11_timers.js) | 0 | ||||
-rw-r--r-- | runtime/rt/11_workers.js (renamed from cli/rt/11_workers.js) | 0 | ||||
-rw-r--r-- | runtime/rt/12_io.js (renamed from cli/rt/12_io.js) | 0 | ||||
-rw-r--r-- | runtime/rt/13_buffer.js (renamed from cli/rt/13_buffer.js) | 0 | ||||
-rw-r--r-- | runtime/rt/27_websocket.js (renamed from cli/rt/27_websocket.js) | 0 | ||||
-rw-r--r-- | runtime/rt/30_files.js (renamed from cli/rt/30_files.js) | 0 | ||||
-rw-r--r-- | runtime/rt/30_fs.js (renamed from cli/rt/30_fs.js) | 0 | ||||
-rw-r--r-- | runtime/rt/30_metrics.js (renamed from cli/rt/30_metrics.js) | 0 | ||||
-rw-r--r-- | runtime/rt/30_net.js (renamed from cli/rt/30_net.js) | 0 | ||||
-rw-r--r-- | runtime/rt/30_os.js (renamed from cli/rt/30_os.js) | 0 | ||||
-rw-r--r-- | runtime/rt/40_compiler_api.js (renamed from cli/rt/40_compiler_api.js) | 0 | ||||
-rw-r--r-- | runtime/rt/40_diagnostics.js (renamed from cli/rt/40_diagnostics.js) | 0 | ||||
-rw-r--r-- | runtime/rt/40_error_stack.js (renamed from cli/rt/40_error_stack.js) | 0 | ||||
-rw-r--r-- | runtime/rt/40_fs_events.js (renamed from cli/rt/40_fs_events.js) | 0 | ||||
-rw-r--r-- | runtime/rt/40_net_unstable.js (renamed from cli/rt/40_net_unstable.js) | 0 | ||||
-rw-r--r-- | runtime/rt/40_performance.js (renamed from cli/rt/40_performance.js) | 0 | ||||
-rw-r--r-- | runtime/rt/40_permissions.js (renamed from cli/rt/40_permissions.js) | 0 | ||||
-rw-r--r-- | runtime/rt/40_plugins.js (renamed from cli/rt/40_plugins.js) | 0 | ||||
-rw-r--r-- | runtime/rt/40_process.js (renamed from cli/rt/40_process.js) | 0 | ||||
-rw-r--r-- | runtime/rt/40_read_file.js (renamed from cli/rt/40_read_file.js) | 0 | ||||
-rw-r--r-- | runtime/rt/40_signals.js (renamed from cli/rt/40_signals.js) | 0 | ||||
-rw-r--r-- | runtime/rt/40_testing.js (renamed from cli/rt/40_testing.js) | 0 | ||||
-rw-r--r-- | runtime/rt/40_tls.js (renamed from cli/rt/40_tls.js) | 0 | ||||
-rw-r--r-- | runtime/rt/40_tty.js (renamed from cli/rt/40_tty.js) | 0 | ||||
-rw-r--r-- | runtime/rt/40_write_file.js (renamed from cli/rt/40_write_file.js) | 0 | ||||
-rw-r--r-- | runtime/rt/41_prompt.js (renamed from cli/rt/41_prompt.js) | 0 | ||||
-rw-r--r-- | runtime/rt/90_deno_ns.js (renamed from cli/rt/90_deno_ns.js) | 0 | ||||
-rw-r--r-- | runtime/rt/99_main.js (renamed from cli/rt/99_main.js) | 0 | ||||
-rw-r--r-- | runtime/rt/README.md (renamed from cli/rt/README.md) | 0 | ||||
-rw-r--r-- | runtime/tokio_util.rs | 25 | ||||
-rw-r--r-- | runtime/web_worker.rs (renamed from cli/web_worker.rs) | 15 | ||||
-rw-r--r-- | runtime/worker.rs (renamed from cli/worker.rs) | 11 |
99 files changed, 1127 insertions, 458 deletions
diff --git a/Cargo.lock b/Cargo.lock index 852c48289..1ed126df5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -460,13 +460,12 @@ dependencies = [ "clap", "crossbeam-channel 0.5.0", "deno_core", - "deno_crypto", "deno_doc", "deno_fetch", "deno_lint", + "deno_runtime", "deno_web", "dissimilar", - "dlopen", "dprint-plugin-typescript", "encoding_rs", "env_logger", @@ -496,7 +495,6 @@ dependencies = [ "swc_bundler", "swc_common", "swc_ecmascript", - "sys-info", "tempfile", "termcolor", "test_util", @@ -506,8 +504,6 @@ dependencies = [ "uuid", "walkdir", "warp", - "webpki", - "webpki-roots", "winapi 0.3.9", "winres", ] @@ -583,6 +579,48 @@ dependencies = [ ] [[package]] +name = "deno_runtime" +version = "0.1.0" +dependencies = [ + "atty", + "deno_core", + "deno_crypto", + "deno_fetch", + "deno_web", + "dlopen", + "encoding_rs", + "env_logger", + "filetime", + "fwdansi", + "http", + "indexmap", + "lazy_static", + "libc", + "log", + "nix", + "notify", + "percent-encoding", + "regex", + "ring", + "rustyline", + "rustyline-derive", + "serde", + "shell-escape", + "sys-info", + "termcolor", + "test_util", + "tokio 0.2.22", + "tokio-rustls", + "tokio-tungstenite", + "uuid", + "warp", + "webpki", + "webpki-roots", + "winapi 0.3.9", + "winres", +] + +[[package]] name = "deno_web" version = "0.21.0" dependencies = [ diff --git a/Cargo.toml b/Cargo.toml index 3281be1af..b7b8adae5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ members = [ "cli", "core", + "runtime", "test_plugin", "test_util", "op_crates/fetch", diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 7bc6221dd..7ad0cc5ca 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -20,10 +20,9 @@ harness = false path = "./bench/main.rs" [build-dependencies] -deno_crypto = { path = "../op_crates/crypto", version = "0.4.0" } deno_core = { path = "../core", version = "0.70.0" } -deno_web = { path = "../op_crates/web", version = "0.21.0" } deno_fetch = { path = "../op_crates/fetch", version = "0.13.0" } +deno_web = { path = "../op_crates/web", version = "0.21.0" } regex = "1.3.9" serde = { version = "1.0.116", features = ["derive"] } @@ -33,11 +32,9 @@ winapi = "0.3.9" [dependencies] deno_core = { path = "../core", version = "0.70.0" } -deno_crypto = { path = "../op_crates/crypto", version = "0.4.0" } deno_doc = "0.1.18" -deno_fetch = { path = "../op_crates/fetch", version = "0.13.0" } deno_lint = "0.2.13" -deno_web = { path = "../op_crates/web", version = "0.21.0" } +deno_runtime = { path = "../runtime", version = "0.1.0" } atty = "0.2.14" base64 = "0.12.3" @@ -46,7 +43,6 @@ byteorder = "1.3.4" clap = "2.33.3" crossbeam-channel = "0.5.0" dissimilar = "1.0.2" -dlopen = "0.1.8" dprint-plugin-typescript = "0.35.1" encoding_rs = "0.8.24" env_logger = "0.7.1" @@ -72,7 +68,6 @@ sourcemap = "6.0.1" swc_bundler = "0.17.6" swc_common = { version = "0.10.7", features = ["sourcemap"] } swc_ecmascript = { version = "0.15.0", features = ["codegen", "dep_graph", "parser", "react", "transforms", "visit"] } -sys-info = "0.7.0" tempfile = "3.1.0" termcolor = "1.1.0" tokio = { version = "0.2.22", features = ["full"] } @@ -82,8 +77,6 @@ tokio-tungstenite = "0.11.0" uuid = { version = "0.8.1", features = ["v4"] } walkdir = "2.3.1" warp = { version = "0.2.5", features = ["tls"] } -webpki = "0.21.3" -webpki-roots = "=0.19.0" # Pinned to v0.19.0 to match 'reqwest'. [target.'cfg(windows)'.dependencies] winapi = { version = "0.3.9", features = ["knownfolders", "mswsock", "objbase", "shlobj", "tlhelp32", "winbase", "winerror", "winsock2"] } diff --git a/cli/build.rs b/cli/build.rs index b0088a9d8..4be71bb9e 100644 --- a/cli/build.rs +++ b/cli/build.rs @@ -13,14 +13,13 @@ use std::env; use std::path::Path; use std::path::PathBuf; +// TODO(bartlomieju): this module contains a lot of duplicated +// logic with `runtime/build.rs`, factor out to `deno_core`. fn create_snapshot( mut js_runtime: JsRuntime, snapshot_path: &Path, files: Vec<PathBuf>, ) { - deno_web::init(&mut js_runtime); - deno_fetch::init(&mut js_runtime); - deno_crypto::init(&mut js_runtime); // TODO(nayeemrmn): https://github.com/rust-lang/cargo/issues/3946 to get the // workspace root. let display_root = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap(); @@ -43,14 +42,6 @@ fn create_snapshot( println!("Snapshot written to: {} ", snapshot_path.display()); } -fn create_runtime_snapshot(snapshot_path: &Path, files: Vec<PathBuf>) { - let js_runtime = JsRuntime::new(RuntimeOptions { - will_snapshot: true, - ..Default::default() - }); - create_snapshot(js_runtime, snapshot_path, files); -} - #[derive(Debug, Deserialize)] struct LoadArgs { /// The fully qualified specifier that should be loaded. @@ -265,12 +256,8 @@ fn main() { let o = PathBuf::from(env::var_os("OUT_DIR").unwrap()); // Main snapshot - let runtime_snapshot_path = o.join("CLI_SNAPSHOT.bin"); let compiler_snapshot_path = o.join("COMPILER_SNAPSHOT.bin"); - let js_files = get_js_files("rt"); - create_runtime_snapshot(&runtime_snapshot_path, js_files); - let js_files = get_js_files("tsc"); create_compiler_snapshot(&compiler_snapshot_path, js_files, &c); diff --git a/cli/errors.rs b/cli/errors.rs index 869cdee2c..29fd428c8 100644 --- a/cli/errors.rs +++ b/cli/errors.rs @@ -12,218 +12,25 @@ use crate::ast::DiagnosticBuffer; use crate::import_map::ImportMapError; use deno_core::error::AnyError; -use deno_core::serde_json; -use deno_core::url; -use deno_core::ModuleResolutionError; -use deno_fetch::reqwest; -use rustyline::error::ReadlineError; -use std::env; -use std::error::Error; -use std::io; - -fn get_dlopen_error_class(error: &dlopen::Error) -> &'static str { - use dlopen::Error::*; - match error { - NullCharacter(_) => "InvalidData", - OpeningLibraryError(ref e) => get_io_error_class(e), - SymbolGettingError(ref e) => get_io_error_class(e), - AddrNotMatchingDll(ref e) => get_io_error_class(e), - NullSymbol => "NotFound", - } -} - -fn get_env_var_error_class(error: &env::VarError) -> &'static str { - use env::VarError::*; - match error { - NotPresent => "NotFound", - NotUnicode(..) => "InvalidData", - } -} fn get_import_map_error_class(_: &ImportMapError) -> &'static str { "URIError" } -fn get_io_error_class(error: &io::Error) -> &'static str { - use io::ErrorKind::*; - match error.kind() { - NotFound => "NotFound", - PermissionDenied => "PermissionDenied", - ConnectionRefused => "ConnectionRefused", - ConnectionReset => "ConnectionReset", - ConnectionAborted => "ConnectionAborted", - NotConnected => "NotConnected", - AddrInUse => "AddrInUse", - AddrNotAvailable => "AddrNotAvailable", - BrokenPipe => "BrokenPipe", - AlreadyExists => "AlreadyExists", - InvalidInput => "TypeError", - InvalidData => "InvalidData", - TimedOut => "TimedOut", - Interrupted => "Interrupted", - WriteZero => "WriteZero", - UnexpectedEof => "UnexpectedEof", - Other => "Error", - WouldBlock => unreachable!(), - // Non-exhaustive enum - might add new variants - // in the future - _ => unreachable!(), - } -} - -fn get_module_resolution_error_class( - _: &ModuleResolutionError, -) -> &'static str { - "URIError" -} - -fn get_notify_error_class(error: ¬ify::Error) -> &'static str { - use notify::ErrorKind::*; - match error.kind { - Generic(_) => "Error", - Io(ref e) => get_io_error_class(e), - PathNotFound => "NotFound", - WatchNotFound => "NotFound", - InvalidConfig(_) => "InvalidData", - } -} - -fn get_readline_error_class(error: &ReadlineError) -> &'static str { - use ReadlineError::*; - match error { - Io(err) => get_io_error_class(err), - Eof => "UnexpectedEof", - Interrupted => "Interrupted", - #[cfg(unix)] - Errno(err) => get_nix_error_class(err), - _ => unimplemented!(), - } -} - -fn get_regex_error_class(error: ®ex::Error) -> &'static str { - use regex::Error::*; - match error { - Syntax(_) => "SyntaxError", - CompiledTooBig(_) => "RangeError", - _ => "Error", - } -} - -fn get_request_error_class(error: &reqwest::Error) -> &'static str { - error - .source() - .and_then(|inner_err| { - (inner_err - .downcast_ref::<io::Error>() - .map(get_io_error_class)) - .or_else(|| { - inner_err - .downcast_ref::<serde_json::error::Error>() - .map(get_serde_json_error_class) - }) - .or_else(|| { - inner_err - .downcast_ref::<url::ParseError>() - .map(get_url_parse_error_class) - }) - }) - .unwrap_or("Http") -} - -fn get_serde_json_error_class( - error: &serde_json::error::Error, -) -> &'static str { - use deno_core::serde_json::error::*; - match error.classify() { - Category::Io => error - .source() - .and_then(|e| e.downcast_ref::<io::Error>()) - .map(get_io_error_class) - .unwrap(), - Category::Syntax => "SyntaxError", - Category::Data => "InvalidData", - Category::Eof => "UnexpectedEof", - } -} - fn get_diagnostic_class(_: &DiagnosticBuffer) -> &'static str { "SyntaxError" } -fn get_url_parse_error_class(_error: &url::ParseError) -> &'static str { - "URIError" -} - -#[cfg(unix)] -fn get_nix_error_class(error: &nix::Error) -> &'static str { - use nix::errno::Errno::*; - match error { - nix::Error::Sys(ECHILD) => "NotFound", - nix::Error::Sys(EINVAL) => "TypeError", - nix::Error::Sys(ENOENT) => "NotFound", - nix::Error::Sys(ENOTTY) => "BadResource", - nix::Error::Sys(EPERM) => "PermissionDenied", - nix::Error::Sys(ESRCH) => "NotFound", - nix::Error::Sys(UnknownErrno) => "Error", - nix::Error::Sys(_) => "Error", - nix::Error::InvalidPath => "TypeError", - nix::Error::InvalidUtf8 => "InvalidData", - nix::Error::UnsupportedOperation => unreachable!(), - } -} - pub(crate) fn get_error_class_name(e: &AnyError) -> &'static str { - deno_core::error::get_custom_error_class(e) - .or_else(|| { - e.downcast_ref::<dlopen::Error>() - .map(get_dlopen_error_class) - }) - .or_else(|| { - e.downcast_ref::<env::VarError>() - .map(get_env_var_error_class) - }) + deno_runtime::errors::get_error_class_name(e) .or_else(|| { e.downcast_ref::<ImportMapError>() .map(get_import_map_error_class) }) - .or_else(|| e.downcast_ref::<io::Error>().map(get_io_error_class)) - .or_else(|| { - e.downcast_ref::<ModuleResolutionError>() - .map(get_module_resolution_error_class) - }) - .or_else(|| { - e.downcast_ref::<notify::Error>() - .map(get_notify_error_class) - }) - .or_else(|| { - e.downcast_ref::<ReadlineError>() - .map(get_readline_error_class) - }) - .or_else(|| { - e.downcast_ref::<reqwest::Error>() - .map(get_request_error_class) - }) - .or_else(|| e.downcast_ref::<regex::Error>().map(get_regex_error_class)) - .or_else(|| { - e.downcast_ref::<serde_json::error::Error>() - .map(get_serde_json_error_class) - }) .or_else(|| { e.downcast_ref::<DiagnosticBuffer>() .map(get_diagnostic_class) }) - .or_else(|| { - e.downcast_ref::<url::ParseError>() - .map(get_url_parse_error_class) - }) - .or_else(|| { - #[cfg(unix)] - let maybe_get_nix_error_class = - || e.downcast_ref::<nix::Error>().map(get_nix_error_class); - #[cfg(not(unix))] - let maybe_get_nix_error_class = || Option::<&'static str>::None; - (maybe_get_nix_error_class)() - }) .unwrap_or_else(|| { panic!("Error '{}' contains boxed error of unknown type", e); }) diff --git a/cli/file_fetcher.rs b/cli/file_fetcher.rs index 7b730e455..86c0ac966 100644 --- a/cli/file_fetcher.rs +++ b/cli/file_fetcher.rs @@ -7,8 +7,8 @@ use crate::http_util::fetch_once; use crate::http_util::get_user_agent; use crate::http_util::FetchOnceResult; use crate::media_type::MediaType; -use crate::permissions::Permissions; use crate::text_encoding; +use deno_runtime::permissions::Permissions; use deno_core::error::custom_error; use deno_core::error::generic_error; @@ -17,7 +17,7 @@ use deno_core::error::AnyError; use deno_core::futures; use deno_core::futures::future::FutureExt; use deno_core::ModuleSpecifier; -use deno_fetch::reqwest; +use deno_runtime::deno_fetch::reqwest; use std::collections::HashMap; use std::fs; use std::future::Future; diff --git a/cli/file_watcher.rs b/cli/file_watcher.rs index 4aa93c581..ef7aae603 100644 --- a/cli/file_watcher.rs +++ b/cli/file_watcher.rs @@ -240,16 +240,17 @@ fn new_watcher( ) -> Result<RecommendedWatcher, AnyError> { let event_detected = Arc::clone(&debounce.event_detected); - let mut watcher: RecommendedWatcher = Watcher::new_immediate( - move |res: Result<NotifyEvent, NotifyError>| { + let mut watcher: RecommendedWatcher = + Watcher::new_immediate(move |res: Result<NotifyEvent, NotifyError>| { if let Ok(event) = res { - if matches!(event.kind, EventKind::Create(_) | EventKind::Modify(_) | EventKind::Remove(_)) - { + if matches!( + event.kind, + EventKind::Create(_) | EventKind::Modify(_) | EventKind::Remove(_) + ) { event_detected.store(true, Ordering::Relaxed); } } - }, - )?; + })?; watcher.configure(Config::PreciseEvents(true)).unwrap(); diff --git a/cli/http_util.rs b/cli/http_util.rs index 4bd59e32b..97e3453ec 100644 --- a/cli/http_util.rs +++ b/cli/http_util.rs @@ -6,16 +6,16 @@ use deno_core::error::generic_error; use deno_core::error::AnyError; use deno_core::futures; use deno_core::url::Url; -use deno_fetch::reqwest; -use deno_fetch::reqwest::header::HeaderMap; -use deno_fetch::reqwest::header::HeaderValue; -use deno_fetch::reqwest::header::IF_NONE_MATCH; -use deno_fetch::reqwest::header::LOCATION; -use deno_fetch::reqwest::header::USER_AGENT; -use deno_fetch::reqwest::redirect::Policy; -use deno_fetch::reqwest::Client; -use deno_fetch::reqwest::Response; -use deno_fetch::reqwest::StatusCode; +use deno_runtime::deno_fetch::reqwest; +use deno_runtime::deno_fetch::reqwest::header::HeaderMap; +use deno_runtime::deno_fetch::reqwest::header::HeaderValue; +use deno_runtime::deno_fetch::reqwest::header::IF_NONE_MATCH; +use deno_runtime::deno_fetch::reqwest::header::LOCATION; +use deno_runtime::deno_fetch::reqwest::header::USER_AGENT; +use deno_runtime::deno_fetch::reqwest::redirect::Policy; +use deno_runtime::deno_fetch::reqwest::Client; +use deno_runtime::deno_fetch::reqwest::Response; +use deno_runtime::deno_fetch::reqwest::StatusCode; use std::cmp::min; use std::collections::HashMap; use std::fs::File; @@ -4,8 +4,6 @@ use deno_core::Snapshot; pub const TS_VERSION: &str = env!("TS_VERSION"); -pub static CLI_SNAPSHOT: &[u8] = - include_bytes!(concat!(env!("OUT_DIR"), "/CLI_SNAPSHOT.bin")); pub static COMPILER_SNAPSHOT: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/COMPILER_SNAPSHOT.bin")); pub static DENO_NS_LIB: &str = include_str!("dts/lib.deno.ns.d.ts"); @@ -16,12 +14,6 @@ pub static SHARED_GLOBALS_LIB: &str = pub static WINDOW_LIB: &str = include_str!("dts/lib.deno.window.d.ts"); pub static UNSTABLE_NS_LIB: &str = include_str!("dts/lib.deno.unstable.d.ts"); -pub fn deno_isolate_init() -> Snapshot { - debug!("Deno isolate init with snapshots."); - let data = CLI_SNAPSHOT; - Snapshot::Static(data) -} - pub fn compiler_isolate_init() -> Snapshot { debug!("Deno compiler isolate init with snapshots."); let data = COMPILER_SNAPSHOT; @@ -29,25 +21,6 @@ pub fn compiler_isolate_init() -> Snapshot { } #[test] -fn cli_snapshot() { - let mut js_runtime = deno_core::JsRuntime::new(deno_core::RuntimeOptions { - startup_snapshot: Some(deno_isolate_init()), - ..Default::default() - }); - js_runtime - .execute( - "<anon>", - r#" - if (!(bootstrap.mainRuntime && bootstrap.workerRuntime)) { - throw Error("bad"); - } - console.log("we have console.log!!!"); - "#, - ) - .unwrap(); -} - -#[test] fn compiler_snapshot() { let mut js_runtime = deno_core::JsRuntime::new(deno_core::RuntimeOptions { startup_snapshot: Some(compiler_isolate_init()), diff --git a/cli/main.rs b/cli/main.rs index 38deec5bb..b6b6b295b 100644 --- a/cli/main.rs +++ b/cli/main.rs @@ -25,19 +25,14 @@ mod http_cache; mod http_util; mod import_map; mod info; -mod inspector; mod js; mod lockfile; mod lsp; mod media_type; -mod metrics; mod module_graph; mod module_loader; mod ops; -mod permissions; mod program_state; -mod resolve_addr; -mod signal; mod source_maps; mod specifier_handler; mod standalone; @@ -47,8 +42,6 @@ mod tools; mod tsc; mod tsc_config; mod version; -mod web_worker; -mod worker; use crate::file_fetcher::File; use crate::file_fetcher::FileFetcher; @@ -59,18 +52,12 @@ use crate::fmt_errors::PrettyJsError; use crate::import_map::ImportMap; use crate::media_type::MediaType; use crate::module_loader::CliModuleLoader; -use crate::ops::worker_host::CreateWebWorkerCb; -use crate::permissions::Permissions; use crate::program_state::exit_unstable; use crate::program_state::ProgramState; use crate::source_maps::apply_source_map; use crate::specifier_handler::FetchHandler; use crate::standalone::create_standalone_binary; use crate::tools::installer::infer_name_from_url; -use crate::web_worker::WebWorker; -use crate::web_worker::WebWorkerOptions; -use crate::worker::MainWorker; -use crate::worker::WorkerOptions; use deno_core::error::generic_error; use deno_core::error::AnyError; use deno_core::futures::future::FutureExt; @@ -81,6 +68,13 @@ use deno_core::v8_set_flags; use deno_core::ModuleSpecifier; use deno_doc as doc; use deno_doc::parser::DocFileLoader; +use deno_runtime::ops::worker_host::CreateWebWorkerCb; +use deno_runtime::permissions::Permissions; +use deno_runtime::permissions::PermissionsOptions; +use deno_runtime::web_worker::WebWorker; +use deno_runtime::web_worker::WebWorkerOptions; +use deno_runtime::worker::MainWorker; +use deno_runtime::worker::WorkerOptions; use log::Level; use log::LevelFilter; use std::cell::RefCell; @@ -93,6 +87,23 @@ use std::pin::Pin; use std::rc::Rc; use std::sync::Arc; +impl From<Flags> for PermissionsOptions { + fn from(flags: Flags) -> Self { + Self { + allow_env: flags.allow_env, + allow_hrtime: flags.allow_hrtime, + allow_net: flags.allow_net, + allow_plugin: flags.allow_plugin, + allow_read: flags.allow_read, + allow_run: flags.allow_run, + allow_write: flags.allow_write, + net_allowlist: flags.net_allowlist, + read_allowlist: flags.read_allowlist, + write_allowlist: flags.write_allowlist, + } + } +} + fn create_web_worker_callback( program_state: Arc<ProgramState>, ) -> Arc<CreateWebWorkerCb> { @@ -132,6 +143,7 @@ fn create_web_worker_callback( runtime_version: version::deno(), ts_version: version::TYPESCRIPT.to_string(), no_color: !colors::use_color(), + get_error_class_fn: Some(&crate::errors::get_error_class_name), }; let mut worker = WebWorker::from_options( @@ -207,6 +219,7 @@ pub fn create_main_worker( runtime_version: version::deno(), ts_version: version::TYPESCRIPT.to_string(), no_color: !colors::use_color(), + get_error_class_fn: Some(&crate::errors::get_error_class_name), }; let mut worker = MainWorker::from_options(main_module, permissions, &options); @@ -392,7 +405,7 @@ async fn install_command( let mut preload_flags = flags.clone(); preload_flags.inspect = None; preload_flags.inspect_brk = None; - let permissions = Permissions::from_flags(&preload_flags); + let permissions = Permissions::from_options(&preload_flags.clone().into()); let program_state = ProgramState::new(preload_flags)?; let main_module = ModuleSpecifier::resolve_url_or_path(&module_url)?; let mut worker = @@ -461,7 +474,7 @@ async fn eval_command( // Force TypeScript compile. let main_module = ModuleSpecifier::resolve_url_or_path("./$deno$eval.ts").unwrap(); - let permissions = Permissions::from_flags(&flags); + let permissions = Permissions::from_options(&flags.clone().into()); let program_state = ProgramState::new(flags)?; let mut worker = create_main_worker(&program_state, main_module.clone(), permissions); @@ -804,7 +817,7 @@ async fn format_command( async fn run_repl(flags: Flags) -> Result<(), AnyError> { let main_module = ModuleSpecifier::resolve_url_or_path("./$deno$repl.ts").unwrap(); - let permissions = Permissions::from_flags(&flags); + let permissions = Permissions::from_options(&flags.clone().into()); let program_state = ProgramState::new(flags)?; let mut worker = create_main_worker(&program_state, main_module.clone(), permissions); @@ -815,7 +828,7 @@ async fn run_repl(flags: Flags) -> Result<(), AnyError> { async fn run_from_stdin(flags: Flags) -> Result<(), AnyError> { let program_state = ProgramState::new(flags.clone())?; - let permissions = Permissions::from_flags(&flags); + let permissions = Permissions::from_options(&flags.clone().into()); let main_module = ModuleSpecifier::resolve_url_or_path("./$deno$stdin.ts").unwrap(); let mut worker = create_main_worker( @@ -896,7 +909,7 @@ async fn run_with_watch(flags: Flags, script: String) -> Result<(), AnyError> { let operation = |main_module: ModuleSpecifier| { let flags = flags.clone(); - let permissions = Permissions::from_flags(&flags); + let permissions = Permissions::from_options(&flags.clone().into()); async move { let main_module = main_module.clone(); let program_state = ProgramState::new(flags)?; @@ -932,7 +945,7 @@ async fn run_command(flags: Flags, script: String) -> Result<(), AnyError> { let main_module = ModuleSpecifier::resolve_url_or_path(&script)?; let program_state = ProgramState::new(flags.clone())?; - let permissions = Permissions::from_flags(&flags); + let permissions = Permissions::from_options(&flags.clone().into()); let mut worker = create_main_worker(&program_state, main_module.clone(), permissions); debug!("main_module {}", main_module); @@ -953,7 +966,7 @@ async fn test_command( filter: Option<String>, ) -> Result<(), AnyError> { let program_state = ProgramState::new(flags.clone())?; - let permissions = Permissions::from_flags(&flags); + let permissions = Permissions::from_options(&flags.clone().into()); let cwd = std::env::current_dir().expect("No current directory"); let include = include.unwrap_or_else(|| vec![".".to_string()]); let test_modules = diff --git a/cli/module_loader.rs b/cli/module_loader.rs index 9dda2c24a..da75b8510 100644 --- a/cli/module_loader.rs +++ b/cli/module_loader.rs @@ -2,7 +2,6 @@ use crate::import_map::ImportMap; use crate::module_graph::TypeLib; -use crate::permissions::Permissions; use crate::program_state::ProgramState; use deno_core::error::AnyError; use deno_core::futures::future::FutureExt; @@ -11,6 +10,7 @@ use deno_core::ModuleLoadId; use deno_core::ModuleLoader; use deno_core::ModuleSpecifier; use deno_core::OpState; +use deno_runtime::permissions::Permissions; use std::cell::RefCell; use std::pin::Pin; use std::rc::Rc; diff --git a/cli/ops/mod.rs b/cli/ops/mod.rs index 56c0f1ad5..24eca3e77 100644 --- a/cli/ops/mod.rs +++ b/cli/ops/mod.rs @@ -1,32 +1,8 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -mod dispatch_minimal; -pub use dispatch_minimal::MinimalOp; - -pub mod crypto; pub mod errors; -pub mod fetch; -pub mod fs; -pub mod fs_events; -pub mod io; -pub mod net; -#[cfg(unix)] -mod net_unix; -pub mod os; -pub mod permissions; -pub mod plugin; -pub mod process; -pub mod runtime; pub mod runtime_compiler; -pub mod signal; -pub mod timers; -pub mod tls; -pub mod tty; -pub mod web_worker; -pub mod websocket; -pub mod worker_host; -use crate::metrics::metrics_op; use deno_core::error::AnyError; use deno_core::json_op_async; use deno_core::json_op_sync; @@ -35,6 +11,7 @@ use deno_core::BufVec; use deno_core::JsRuntime; use deno_core::OpState; use deno_core::ZeroCopyBuf; +use deno_runtime::metrics::metrics_op; use std::cell::RefCell; use std::future::Future; use std::rc::Rc; @@ -54,34 +31,3 @@ where { rt.register_op(name, metrics_op(json_op_sync(op_fn))); } - -pub struct UnstableChecker { - pub unstable: bool, -} - -impl UnstableChecker { - /// Quits the process if the --unstable flag was not provided. - /// - /// This is intentionally a non-recoverable check so that people cannot probe - /// for unstable APIs from stable programs. - // NOTE(bartlomieju): keep in sync with `cli/program_state.rs` - pub fn check_unstable(&self, api_name: &str) { - if !self.unstable { - eprintln!( - "Unstable API '{}'. The --unstable flag must be provided.", - api_name - ); - std::process::exit(70); - } - } -} -/// Helper for checking unstable features. Used for sync ops. -pub fn check_unstable(state: &OpState, api_name: &str) { - state.borrow::<UnstableChecker>().check_unstable(api_name) -} - -/// Helper for checking unstable features. Used for async ops. -pub fn check_unstable2(state: &Rc<RefCell<OpState>>, api_name: &str) { - let state = state.borrow(); - state.borrow::<UnstableChecker>().check_unstable(api_name) -} diff --git a/cli/ops/runtime_compiler.rs b/cli/ops/runtime_compiler.rs index 03ba88c76..ec9806e60 100644 --- a/cli/ops/runtime_compiler.rs +++ b/cli/ops/runtime_compiler.rs @@ -6,12 +6,12 @@ use crate::media_type::MediaType; use crate::module_graph::BundleType; use crate::module_graph::EmitOptions; use crate::module_graph::GraphBuilder; -use crate::permissions::Permissions; use crate::program_state::ProgramState; use crate::specifier_handler::FetchHandler; use crate::specifier_handler::MemoryHandler; use crate::specifier_handler::SpecifierHandler; use crate::tsc_config; +use deno_runtime::permissions::Permissions; use std::sync::Arc; use deno_core::error::AnyError; @@ -49,9 +49,9 @@ async fn op_compile( ) -> Result<Value, AnyError> { let args: CompileArgs = serde_json::from_value(args)?; if args.bundle { - super::check_unstable2(&state, "Deno.bundle"); + deno_runtime::ops::check_unstable2(&state, "Deno.bundle"); } else { - super::check_unstable2(&state, "Deno.compile"); + deno_runtime::ops::check_unstable2(&state, "Deno.compile"); } let program_state = state.borrow().borrow::<Arc<ProgramState>>().clone(); let runtime_permissions = { @@ -113,7 +113,7 @@ async fn op_transpile( args: Value, _data: BufVec, ) -> Result<Value, AnyError> { - super::check_unstable2(&state, "Deno.transpileOnly"); + deno_runtime::ops::check_unstable2(&state, "Deno.transpileOnly"); let args: TranspileArgs = serde_json::from_value(args)?; let mut compiler_options = tsc_config::TsConfig::new(json!({ diff --git a/cli/program_state.rs b/cli/program_state.rs index 7b86b7de5..223d043ba 100644 --- a/cli/program_state.rs +++ b/cli/program_state.rs @@ -7,16 +7,16 @@ use crate::flags; use crate::http_cache; use crate::http_util; use crate::import_map::ImportMap; -use crate::inspector::InspectorServer; use crate::lockfile::Lockfile; use crate::media_type::MediaType; use crate::module_graph::CheckOptions; use crate::module_graph::GraphBuilder; use crate::module_graph::TranspileOptions; use crate::module_graph::TypeLib; -use crate::permissions::Permissions; use crate::source_maps::SourceMapGetter; use crate::specifier_handler::FetchHandler; +use deno_runtime::inspector::InspectorServer; +use deno_runtime::permissions::Permissions; use deno_core::error::generic_error; use deno_core::error::AnyError; diff --git a/cli/signal.rs b/cli/signal.rs deleted file mode 100644 index b597714f4..000000000 --- a/cli/signal.rs +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. - -use deno_core::error::AnyError; - -#[cfg(not(unix))] -use deno_core::error::last_os_error; -#[cfg(not(unix))] -use deno_core::error::type_error; - -#[cfg(not(unix))] -const SIGINT: i32 = 2; -#[cfg(not(unix))] -const SIGKILL: i32 = 9; -#[cfg(not(unix))] -const SIGTERM: i32 = 15; - -#[cfg(not(unix))] -use winapi::{ - shared::minwindef::DWORD, - um::{ - handleapi::CloseHandle, - processthreadsapi::{OpenProcess, TerminateProcess}, - winnt::PROCESS_TERMINATE, - }, -}; - -#[cfg(unix)] -pub fn kill(pid: i32, signo: i32) -> Result<(), AnyError> { - use nix::sys::signal::{kill as unix_kill, Signal}; - use nix::unistd::Pid; - use std::convert::TryFrom; - let sig = Signal::try_from(signo)?; - unix_kill(Pid::from_raw(pid), Option::Some(sig)).map_err(AnyError::from) -} - -#[cfg(not(unix))] -pub fn kill(pid: i32, signal: i32) -> Result<(), AnyError> { - match signal { - SIGINT | SIGKILL | SIGTERM => { - if pid <= 0 { - return Err(type_error("unsupported pid")); - } - unsafe { - let handle = OpenProcess(PROCESS_TERMINATE, 0, pid as DWORD); - if handle.is_null() { - return Err(last_os_error()); - } - if TerminateProcess(handle, 1) == 0 { - CloseHandle(handle); - return Err(last_os_error()); - } - if CloseHandle(handle) == 0 { - return Err(last_os_error()); - } - } - } - _ => { - return Err(type_error("unsupported signal")); - } - } - Ok(()) -} diff --git a/cli/specifier_handler.rs b/cli/specifier_handler.rs index 083316740..02a1196d3 100644 --- a/cli/specifier_handler.rs +++ b/cli/specifier_handler.rs @@ -5,8 +5,8 @@ use crate::deno_dir::DenoDir; use crate::disk_cache::DiskCache; use crate::file_fetcher::FileFetcher; use crate::media_type::MediaType; -use crate::permissions::Permissions; use crate::program_state::ProgramState; +use deno_runtime::permissions::Permissions; use deno_core::error::custom_error; use deno_core::error::AnyError; diff --git a/cli/standalone.rs b/cli/standalone.rs index 6559242bd..fea42fc96 100644 --- a/cli/standalone.rs +++ b/cli/standalone.rs @@ -1,10 +1,7 @@ use crate::colors; use crate::flags::Flags; -use crate::permissions::Permissions; use crate::tokio_util; use crate::version; -use crate::worker::MainWorker; -use crate::worker::WorkerOptions; use deno_core::error::bail; use deno_core::error::type_error; use deno_core::error::AnyError; @@ -12,6 +9,9 @@ use deno_core::futures::FutureExt; use deno_core::ModuleLoader; use deno_core::ModuleSpecifier; use deno_core::OpState; +use deno_runtime::permissions::Permissions; +use deno_runtime::worker::MainWorker; +use deno_runtime::worker::WorkerOptions; use std::cell::RefCell; use std::convert::TryInto; use std::env::current_exe; @@ -135,6 +135,7 @@ async fn run(source_code: String, args: Vec<String>) -> Result<(), AnyError> { runtime_version: version::deno(), ts_version: version::TYPESCRIPT.to_string(), no_color: !colors::use_color(), + get_error_class_fn: Some(&crate::errors::get_error_class_name), }; let mut worker = MainWorker::from_options(main_module.clone(), permissions, &options); diff --git a/cli/tools/coverage.rs b/cli/tools/coverage.rs index 726ce9749..229cb8020 100644 --- a/cli/tools/coverage.rs +++ b/cli/tools/coverage.rs @@ -1,11 +1,11 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. use crate::colors; -use crate::inspector::InspectorSession; use deno_core::error::AnyError; use deno_core::serde_json; use deno_core::serde_json::json; use deno_core::url::Url; +use deno_runtime::inspector::InspectorSession; use serde::Deserialize; pub struct CoverageCollector { diff --git a/cli/tools/repl.rs b/cli/tools/repl.rs index 9b4d94a23..61d7809c3 100644 --- a/cli/tools/repl.rs +++ b/cli/tools/repl.rs @@ -3,13 +3,13 @@ use crate::ast; use crate::ast::TokenOrComment; use crate::colors; -use crate::inspector::InspectorSession; use crate::media_type::MediaType; use crate::program_state::ProgramState; -use crate::worker::MainWorker; use deno_core::error::AnyError; use deno_core::serde_json::json; use deno_core::serde_json::Value; +use deno_runtime::inspector::InspectorSession; +use deno_runtime::worker::MainWorker; use rustyline::completion::Completer; use rustyline::error::ReadlineError; use rustyline::highlight::Highlighter; diff --git a/cli/tools/upgrade.rs b/cli/tools/upgrade.rs index b76850dde..da26b3159 100644 --- a/cli/tools/upgrade.rs +++ b/cli/tools/upgrade.rs @@ -3,8 +3,8 @@ //! This module provides feature to upgrade deno executable use crate::AnyError; -use deno_fetch::reqwest; -use deno_fetch::reqwest::Client; +use deno_runtime::deno_fetch::reqwest; +use deno_runtime::deno_fetch::reqwest::Client; use semver_parser::version::parse as semver_parse; use std::fs; use std::path::Path; diff --git a/core/error.rs b/core/error.rs index 1d31df5ed..8e4138889 100644 --- a/core/error.rs +++ b/core/error.rs @@ -12,7 +12,6 @@ use std::fmt; use std::fmt::Debug; use std::fmt::Display; use std::fmt::Formatter; -use std::io; /// A generic wrapper that can encapsulate any concrete error type. pub type AnyError = anyhow::Error; @@ -41,10 +40,6 @@ pub fn uri_error(message: impl Into<Cow<'static, str>>) -> AnyError { custom_error("URIError", message) } -pub fn last_os_error() -> AnyError { - io::Error::last_os_error().into() -} - pub fn bad_resource(message: impl Into<Cow<'static, str>>) -> AnyError { custom_error("BadResource", message) } diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml new file mode 100644 index 000000000..fa097064e --- /dev/null +++ b/runtime/Cargo.toml @@ -0,0 +1,74 @@ +# Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. + +[package] +name = "deno_runtime" +version = "0.1.0" +license = "MIT" +authors = ["the Deno authors"] +edition = "2018" +description = "Provides the deno runtime library" +repository = "https://github.com/denoland/deno" + +[lib] +name = "deno_runtime" +path = "lib.rs" + +[[example]] +name = "hello_runtime" +path = "examples/hello_runtime.rs" + +[build-dependencies] +deno_crypto = { path = "../op_crates/crypto", version = "0.4.0" } +deno_core = { path = "../core", version = "0.70.0" } +deno_web = { path = "../op_crates/web", version = "0.21.0" } +deno_fetch = { path = "../op_crates/fetch", version = "0.13.0" } + +[target.'cfg(windows)'.build-dependencies] +winres = "0.1.11" +winapi = "0.3.9" + +[dependencies] +deno_core = { path = "../core", version = "0.70.0" } +deno_crypto = { path = "../op_crates/crypto", version = "0.4.0" } +deno_fetch = { path = "../op_crates/fetch", version = "0.13.0" } +deno_web = { path = "../op_crates/web", version = "0.21.0" } + +atty = "0.2.14" +dlopen = "0.1.8" +encoding_rs = "0.8.24" +env_logger = "0.7.1" +filetime = "0.2.12" +http = "0.2.1" +indexmap = "1.6.0" +lazy_static = "1.4.0" +libc = "0.2.77" +log = "0.4.11" +notify = "5.0.0-pre.3" +percent-encoding = "2.1.0" +regex = "1.3.9" +ring = "0.16.19" +rustyline = { version = "7.0.0", default-features = false } +rustyline-derive = "0.4.0" +serde = { version = "1.0.116", features = ["derive"] } +shell-escape = "0.1.5" +sys-info = "0.7.0" +termcolor = "1.1.0" +tokio = { version = "0.2.22", features = ["full"] } +tokio-rustls = "0.14.1" +# Keep in-sync with warp. +tokio-tungstenite = "0.11.0" +uuid = { version = "0.8.1", features = ["v4"] } +warp = { version = "0.2.5", features = ["tls"] } +webpki = "0.21.3" +webpki-roots = "=0.19.0" # Pinned to v0.19.0 to match 'reqwest'. + +[target.'cfg(windows)'.dependencies] +winapi = { version = "0.3.9", features = ["knownfolders", "mswsock", "objbase", "shlobj", "tlhelp32", "winbase", "winerror", "winsock2"] } +fwdansi = "1.1.0" + +[target.'cfg(unix)'.dependencies] +nix = "0.19.0" + +[dev-dependencies] +# Used in benchmark +test_util = { path = "../test_util" } diff --git a/runtime/README.md b/runtime/README.md new file mode 100644 index 000000000..1056ac5b6 --- /dev/null +++ b/runtime/README.md @@ -0,0 +1,44 @@ +# `deno_runtime` crate + +[](https://crates.io/crates/deno_runtime) +[](https://docs.rs/deno_runtime) + +This is a slim version of the Deno CLI which removes typescript integration and +various tooling (like lint and doc). Basically only JavaScript execution with +Deno's operating system bindings (ops). + +## Stability + +This crate is built using battle-tested modules that were originally in `deno` +crate, however the API of this crate is subject to rapid and breaking changes. + +## `MainWorker` + +The main API of this crate is `MainWorker`. `MainWorker` is a structure +encapsulating `deno_core::JsRuntime` with a set of ops used to implement `Deno` +namespace. + +When creating a `MainWorker` implementors must call `MainWorker::bootstrap` to +prepare JS runtime for use. + +`MainWorker` is highly configurable and allows to customize many of the +runtime's properties: + +- module loading implementation +- error formatting +- support for source maps +- support for V8 inspector and Chrome Devtools debugger +- HTTP client user agent, CA certificate +- random number generator seed + +## `Worker` Web API + +`deno_runtime` comes with support for `Worker` Web API. The `Worker` API is +implemented using `WebWorker` structure. + +When creating a new instance of `MainWorker` implementors must provide a +callback function that is used when creating a new instance of `Worker`. + +All `WebWorker` instances are decendents of `MainWorker` which is responsible +for setting up communication with child worker. Each `WebWorker` spawns a new OS +thread that is dedicated solely to that worker. diff --git a/runtime/build.rs b/runtime/build.rs new file mode 100644 index 000000000..7c74c9793 --- /dev/null +++ b/runtime/build.rs @@ -0,0 +1,81 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. + +use deno_core::JsRuntime; +use deno_core::RuntimeOptions; +use std::env; +use std::path::Path; +use std::path::PathBuf; + +// TODO(bartlomieju): this module contains a lot of duplicated +// logic with `cli/build.rs`, factor out to `deno_core`. +fn create_snapshot( + mut js_runtime: JsRuntime, + snapshot_path: &Path, + files: Vec<PathBuf>, +) { + deno_web::init(&mut js_runtime); + deno_fetch::init(&mut js_runtime); + deno_crypto::init(&mut js_runtime); + // TODO(nayeemrmn): https://github.com/rust-lang/cargo/issues/3946 to get the + // workspace root. + let display_root = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap(); + for file in files { + println!("cargo:rerun-if-changed={}", file.display()); + let display_path = file.strip_prefix(display_root).unwrap(); + let display_path_str = display_path.display().to_string(); + js_runtime + .execute( + &("deno:".to_string() + &display_path_str.replace('\\', "/")), + &std::fs::read_to_string(&file).unwrap(), + ) + .unwrap(); + } + + let snapshot = js_runtime.snapshot(); + let snapshot_slice: &[u8] = &*snapshot; + println!("Snapshot size: {}", snapshot_slice.len()); + std::fs::write(&snapshot_path, snapshot_slice).unwrap(); + println!("Snapshot written to: {} ", snapshot_path.display()); +} + +fn create_runtime_snapshot(snapshot_path: &Path, files: Vec<PathBuf>) { + let js_runtime = JsRuntime::new(RuntimeOptions { + will_snapshot: true, + ..Default::default() + }); + create_snapshot(js_runtime, snapshot_path, files); +} + +fn main() { + // Don't build V8 if "cargo doc" is being run. This is to support docs.rs. + if env::var_os("RUSTDOCFLAGS").is_some() { + return; + } + + // To debug snapshot issues uncomment: + // op_fetch_asset::trace_serializer(); + + println!("cargo:rustc-env=TARGET={}", env::var("TARGET").unwrap()); + println!("cargo:rustc-env=PROFILE={}", env::var("PROFILE").unwrap()); + let o = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + + // Main snapshot + let runtime_snapshot_path = o.join("CLI_SNAPSHOT.bin"); + + let js_files = get_js_files("rt"); + create_runtime_snapshot(&runtime_snapshot_path, js_files); +} + +fn get_js_files(d: &str) -> Vec<PathBuf> { + let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR")); + let mut js_files = std::fs::read_dir(d) + .unwrap() + .map(|dir_entry| { + let file = dir_entry.unwrap(); + manifest_dir.join(file.path()) + }) + .filter(|path| path.extension().unwrap_or_default() == "js") + .collect::<Vec<PathBuf>>(); + js_files.sort(); + js_files +} diff --git a/runtime/colors.rs b/runtime/colors.rs new file mode 100644 index 000000000..93f252716 --- /dev/null +++ b/runtime/colors.rs @@ -0,0 +1,130 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. + +use regex::Regex; +use std::env; +use std::fmt; +use std::io::Write; +use termcolor::Color::{Ansi256, Black, Blue, Cyan, Green, Red, White, Yellow}; +use termcolor::{Ansi, ColorSpec, WriteColor}; + +#[cfg(windows)] +use termcolor::{BufferWriter, ColorChoice}; + +lazy_static! { + // STRIP_ANSI_RE and strip_ansi_codes are lifted from the "console" crate. + // Copyright 2017 Armin Ronacher <armin.ronacher@active-4.com>. MIT License. + static ref STRIP_ANSI_RE: Regex = Regex::new( + r"[\x1b\x9b][\[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-PRZcf-nqry=><]" + ).unwrap(); + static ref NO_COLOR: bool = { + env::var_os("NO_COLOR").is_some() + }; +} + +/// Helper function to strip ansi codes. +#[cfg(test)] +pub fn strip_ansi_codes(s: &str) -> std::borrow::Cow<str> { + STRIP_ANSI_RE.replace_all(s, "") +} + +pub fn use_color() -> bool { + !(*NO_COLOR) +} + +#[cfg(windows)] +pub fn enable_ansi() { + BufferWriter::stdout(ColorChoice::AlwaysAnsi); +} + +fn style(s: &str, colorspec: ColorSpec) -> impl fmt::Display { + if !use_color() { + return String::from(s); + } + let mut v = Vec::new(); + let mut ansi_writer = Ansi::new(&mut v); + ansi_writer.set_color(&colorspec).unwrap(); + ansi_writer.write_all(s.as_bytes()).unwrap(); + ansi_writer.reset().unwrap(); + String::from_utf8_lossy(&v).into_owned() +} + +pub fn red_bold(s: &str) -> impl fmt::Display { + let mut style_spec = ColorSpec::new(); + style_spec.set_fg(Some(Red)).set_bold(true); + style(&s, style_spec) +} + +pub fn green_bold(s: &str) -> impl fmt::Display { + let mut style_spec = ColorSpec::new(); + style_spec.set_fg(Some(Green)).set_bold(true); + style(&s, style_spec) +} + +pub fn italic_bold(s: &str) -> impl fmt::Display { + let mut style_spec = ColorSpec::new(); + style_spec.set_bold(true).set_italic(true); + style(&s, style_spec) +} + +pub fn white_on_red(s: &str) -> impl fmt::Display { + let mut style_spec = ColorSpec::new(); + style_spec.set_bg(Some(Red)).set_fg(Some(White)); + style(&s, style_spec) +} + +pub fn black_on_green(s: &str) -> impl fmt::Display { + let mut style_spec = ColorSpec::new(); + style_spec.set_bg(Some(Green)).set_fg(Some(Black)); + style(&s, style_spec) +} + +pub fn yellow(s: &str) -> impl fmt::Display { + let mut style_spec = ColorSpec::new(); + style_spec.set_fg(Some(Yellow)); + style(&s, style_spec) +} + +pub fn cyan(s: &str) -> impl fmt::Display { + let mut style_spec = ColorSpec::new(); + style_spec.set_fg(Some(Cyan)); + style(&s, style_spec) +} + +pub fn red(s: &str) -> impl fmt::Display { + let mut style_spec = ColorSpec::new(); + style_spec.set_fg(Some(Red)); + style(&s, style_spec) +} + +pub fn green(s: &str) -> impl fmt::Display { + let mut style_spec = ColorSpec::new(); + style_spec.set_fg(Some(Green)); + style(&s, style_spec) +} + +pub fn bold(s: &str) -> impl fmt::Display { + let mut style_spec = ColorSpec::new(); + style_spec.set_bold(true); + style(&s, style_spec) +} + +pub fn gray(s: &str) -> impl fmt::Display { + let mut style_spec = ColorSpec::new(); + style_spec.set_fg(Some(Ansi256(8))); + style(&s, style_spec) +} + +pub fn italic_bold_gray(s: &str) -> impl fmt::Display { + let mut style_spec = ColorSpec::new(); + style_spec + .set_fg(Some(Ansi256(8))) + .set_bold(true) + .set_italic(true); + style(&s, style_spec) +} + +pub fn intense_blue(s: &str) -> impl fmt::Display { + let mut style_spec = ColorSpec::new(); + style_spec.set_fg(Some(Blue)).set_intense(true); + style(&s, style_spec) +} diff --git a/runtime/errors.rs b/runtime/errors.rs new file mode 100644 index 000000000..f8f71a859 --- /dev/null +++ b/runtime/errors.rs @@ -0,0 +1,209 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. + +//! There are many types of errors in Deno: +//! - AnyError: a generic wrapper that can encapsulate any type of error. +//! - JsError: a container for the error message and stack trace for exceptions +//! thrown in JavaScript code. We use this to pretty-print stack traces. +//! - Diagnostic: these are errors that originate in TypeScript's compiler. +//! They're similar to JsError, in that they have line numbers. But +//! Diagnostics are compile-time type errors, whereas JsErrors are runtime +//! exceptions. + +use deno_core::error::AnyError; +use deno_core::serde_json; +use deno_core::url; +use deno_core::ModuleResolutionError; +use deno_fetch::reqwest; +use rustyline::error::ReadlineError; +use std::env; +use std::error::Error; +use std::io; + +fn get_dlopen_error_class(error: &dlopen::Error) -> &'static str { + use dlopen::Error::*; + match error { + NullCharacter(_) => "InvalidData", + OpeningLibraryError(ref e) => get_io_error_class(e), + SymbolGettingError(ref e) => get_io_error_class(e), + AddrNotMatchingDll(ref e) => get_io_error_class(e), + NullSymbol => "NotFound", + } +} + +fn get_env_var_error_class(error: &env::VarError) -> &'static str { + use env::VarError::*; + match error { + NotPresent => "NotFound", + NotUnicode(..) => "InvalidData", + } +} + +fn get_io_error_class(error: &io::Error) -> &'static str { + use io::ErrorKind::*; + match error.kind() { + NotFound => "NotFound", + PermissionDenied => "PermissionDenied", + ConnectionRefused => "ConnectionRefused", + ConnectionReset => "ConnectionReset", + ConnectionAborted => "ConnectionAborted", + NotConnected => "NotConnected", + AddrInUse => "AddrInUse", + AddrNotAvailable => "AddrNotAvailable", + BrokenPipe => "BrokenPipe", + AlreadyExists => "AlreadyExists", + InvalidInput => "TypeError", + InvalidData => "InvalidData", + TimedOut => "TimedOut", + Interrupted => "Interrupted", + WriteZero => "WriteZero", + UnexpectedEof => "UnexpectedEof", + Other => "Error", + WouldBlock => unreachable!(), + // Non-exhaustive enum - might add new variants + // in the future + _ => unreachable!(), + } +} + +fn get_module_resolution_error_class( + _: &ModuleResolutionError, +) -> &'static str { + "URIError" +} + +fn get_notify_error_class(error: ¬ify::Error) -> &'static str { + use notify::ErrorKind::*; + match error.kind { + Generic(_) => "Error", + Io(ref e) => get_io_error_class(e), + PathNotFound => "NotFound", + WatchNotFound => "NotFound", + InvalidConfig(_) => "InvalidData", + } +} + +fn get_readline_error_class(error: &ReadlineError) -> &'static str { + use ReadlineError::*; + match error { + Io(err) => get_io_error_class(err), + Eof => "UnexpectedEof", + Interrupted => "Interrupted", + #[cfg(unix)] + Errno(err) => get_nix_error_class(err), + _ => unimplemented!(), + } +} + +fn get_regex_error_class(error: ®ex::Error) -> &'static str { + use regex::Error::*; + match error { + Syntax(_) => "SyntaxError", + CompiledTooBig(_) => "RangeError", + _ => "Error", + } +} + +fn get_request_error_class(error: &reqwest::Error) -> &'static str { + error + .source() + .and_then(|inner_err| { + (inner_err + .downcast_ref::<io::Error>() + .map(get_io_error_class)) + .or_else(|| { + inner_err + .downcast_ref::<serde_json::error::Error>() + .map(get_serde_json_error_class) + }) + .or_else(|| { + inner_err + .downcast_ref::<url::ParseError>() + .map(get_url_parse_error_class) + }) + }) + .unwrap_or("Http") +} + +fn get_serde_json_error_class( + error: &serde_json::error::Error, +) -> &'static str { + use deno_core::serde_json::error::*; + match error.classify() { + Category::Io => error + .source() + .and_then(|e| e.downcast_ref::<io::Error>()) + .map(get_io_error_class) + .unwrap(), + Category::Syntax => "SyntaxError", + Category::Data => "InvalidData", + Category::Eof => "UnexpectedEof", + } +} + +fn get_url_parse_error_class(_error: &url::ParseError) -> &'static str { + "URIError" +} + +#[cfg(unix)] +fn get_nix_error_class(error: &nix::Error) -> &'static str { + use nix::errno::Errno::*; + match error { + nix::Error::Sys(ECHILD) => "NotFound", + nix::Error::Sys(EINVAL) => "TypeError", + nix::Error::Sys(ENOENT) => "NotFound", + nix::Error::Sys(ENOTTY) => "BadResource", + nix::Error::Sys(EPERM) => "PermissionDenied", + nix::Error::Sys(ESRCH) => "NotFound", + nix::Error::Sys(UnknownErrno) => "Error", + nix::Error::Sys(_) => "Error", + nix::Error::InvalidPath => "TypeError", + nix::Error::InvalidUtf8 => "InvalidData", + nix::Error::UnsupportedOperation => unreachable!(), + } +} + +pub fn get_error_class_name(e: &AnyError) -> Option<&'static str> { + deno_core::error::get_custom_error_class(e) + .or_else(|| { + e.downcast_ref::<dlopen::Error>() + .map(get_dlopen_error_class) + }) + .or_else(|| { + e.downcast_ref::<env::VarError>() + .map(get_env_var_error_class) + }) + .or_else(|| e.downcast_ref::<io::Error>().map(get_io_error_class)) + .or_else(|| { + e.downcast_ref::<ModuleResolutionError>() + .map(get_module_resolution_error_class) + }) + .or_else(|| { + e.downcast_ref::<notify::Error>() + .map(get_notify_error_class) + }) + .or_else(|| { + e.downcast_ref::<ReadlineError>() + .map(get_readline_error_class) + }) + .or_else(|| { + e.downcast_ref::<reqwest::Error>() + .map(get_request_error_class) + }) + .or_else(|| e.downcast_ref::<regex::Error>().map(get_regex_error_class)) + .or_else(|| { + e.downcast_ref::<serde_json::error::Error>() + .map(get_serde_json_error_class) + }) + .or_else(|| { + e.downcast_ref::<url::ParseError>() + .map(get_url_parse_error_class) + }) + .or_else(|| { + #[cfg(unix)] + let maybe_get_nix_error_class = + || e.downcast_ref::<nix::Error>().map(get_nix_error_class); + #[cfg(not(unix))] + let maybe_get_nix_error_class = || Option::<&'static str>::None; + (maybe_get_nix_error_class)() + }) +} diff --git a/runtime/examples/hello_runtime.js b/runtime/examples/hello_runtime.js new file mode 100644 index 000000000..46609c7a0 --- /dev/null +++ b/runtime/examples/hello_runtime.js @@ -0,0 +1,2 @@ +console.log("Hello world!"); +console.log(Deno); diff --git a/runtime/examples/hello_runtime.rs b/runtime/examples/hello_runtime.rs new file mode 100644 index 000000000..dbe539281 --- /dev/null +++ b/runtime/examples/hello_runtime.rs @@ -0,0 +1,55 @@ +// Copyright 2020 the Deno authors. All rights reserved. MIT license. + +use deno_core::error::AnyError; +use deno_core::FsModuleLoader; +use deno_core::ModuleSpecifier; +use deno_runtime::permissions::Permissions; +use deno_runtime::worker::MainWorker; +use deno_runtime::worker::WorkerOptions; +use std::path::Path; +use std::rc::Rc; +use std::sync::Arc; + +fn get_error_class_name(e: &AnyError) -> &'static str { + deno_runtime::errors::get_error_class_name(e).unwrap_or("Error") +} + +#[tokio::main] +async fn main() -> Result<(), AnyError> { + let module_loader = Rc::new(FsModuleLoader); + let create_web_worker_cb = Arc::new(|_| { + todo!("Web workers are not supported in the example"); + }); + + let options = WorkerOptions { + apply_source_maps: false, + args: vec![], + debug_flag: false, + unstable: false, + ca_filepath: None, + user_agent: "hello_runtime".to_string(), + seed: None, + js_error_create_fn: None, + create_web_worker_cb, + attach_inspector: false, + maybe_inspector_server: None, + should_break_on_first_statement: false, + module_loader, + runtime_version: "x".to_string(), + ts_version: "x".to_string(), + no_color: false, + get_error_class_fn: Some(&get_error_class_name), + }; + + let js_path = + Path::new(env!("CARGO_MANIFEST_DIR")).join("examples/hello_runtime.js"); + let main_module = ModuleSpecifier::resolve_path(&js_path.to_string_lossy())?; + let permissions = Permissions::allow_all(); + + let mut worker = + MainWorker::from_options(main_module.clone(), permissions, &options); + worker.bootstrap(&options); + worker.execute_module(&main_module).await?; + worker.run_event_loop().await?; + Ok(()) +} diff --git a/runtime/fs_util.rs b/runtime/fs_util.rs new file mode 100644 index 000000000..028538d4f --- /dev/null +++ b/runtime/fs_util.rs @@ -0,0 +1,80 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. + +use deno_core::error::AnyError; +pub use deno_core::normalize_path; +use std::env::current_dir; +use std::io::Error; +use std::path::{Path, PathBuf}; + +/// Similar to `std::fs::canonicalize()` but strips UNC prefixes on Windows. +pub fn canonicalize_path(path: &Path) -> Result<PathBuf, Error> { + let mut canonicalized_path = path.canonicalize()?; + if cfg!(windows) { + canonicalized_path = PathBuf::from( + canonicalized_path + .display() + .to_string() + .trim_start_matches("\\\\?\\"), + ); + } + Ok(canonicalized_path) +} + +pub fn resolve_from_cwd(path: &Path) -> Result<PathBuf, AnyError> { + let resolved_path = if path.is_absolute() { + path.to_owned() + } else { + let cwd = current_dir().unwrap(); + cwd.join(path) + }; + + Ok(normalize_path(&resolved_path)) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn resolve_from_cwd_child() { + let cwd = current_dir().unwrap(); + assert_eq!(resolve_from_cwd(Path::new("a")).unwrap(), cwd.join("a")); + } + + #[test] + fn resolve_from_cwd_dot() { + let cwd = current_dir().unwrap(); + assert_eq!(resolve_from_cwd(Path::new(".")).unwrap(), cwd); + } + + #[test] + fn resolve_from_cwd_parent() { + let cwd = current_dir().unwrap(); + assert_eq!(resolve_from_cwd(Path::new("a/..")).unwrap(), cwd); + } + + #[test] + fn test_normalize_path() { + assert_eq!(normalize_path(Path::new("a/../b")), PathBuf::from("b")); + assert_eq!(normalize_path(Path::new("a/./b/")), PathBuf::from("a/b/")); + assert_eq!( + normalize_path(Path::new("a/./b/../c")), + PathBuf::from("a/c") + ); + + if cfg!(windows) { + assert_eq!( + normalize_path(Path::new("C:\\a\\.\\b\\..\\c")), + PathBuf::from("C:\\a\\c") + ); + } + } + + // TODO: Get a good expected value here for Windows. + #[cfg(not(windows))] + #[test] + fn resolve_from_cwd_absolute() { + let expected = Path::new("/a"); + assert_eq!(resolve_from_cwd(expected).unwrap(), expected); + } +} diff --git a/runtime/http_util.rs b/runtime/http_util.rs new file mode 100644 index 000000000..67703c214 --- /dev/null +++ b/runtime/http_util.rs @@ -0,0 +1,46 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. + +use deno_core::error::generic_error; +use deno_core::error::AnyError; +use deno_fetch::reqwest; +use deno_fetch::reqwest::header::HeaderMap; +use deno_fetch::reqwest::header::USER_AGENT; +use deno_fetch::reqwest::redirect::Policy; +use deno_fetch::reqwest::Client; +use std::fs::File; +use std::io::Read; + +/// Create new instance of async reqwest::Client. This client supports +/// proxies and doesn't follow redirects. +pub fn create_http_client( + user_agent: String, + ca_file: Option<&str>, +) -> Result<Client, AnyError> { + let mut headers = HeaderMap::new(); + headers.insert(USER_AGENT, user_agent.parse().unwrap()); + let mut builder = Client::builder() + .redirect(Policy::none()) + .default_headers(headers) + .use_rustls_tls(); + + if let Some(ca_file) = ca_file { + let mut buf = Vec::new(); + File::open(ca_file)?.read_to_end(&mut buf)?; + let cert = reqwest::Certificate::from_pem(&buf)?; + builder = builder.add_root_certificate(cert); + } + + builder + .build() + .map_err(|_| generic_error("Unable to build http client")) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn create_test_client() { + create_http_client("test_client".to_string(), None).unwrap(); + } +} diff --git a/cli/inspector.rs b/runtime/inspector.rs index 89fd5bf57..89fd5bf57 100644 --- a/cli/inspector.rs +++ b/runtime/inspector.rs diff --git a/runtime/js.rs b/runtime/js.rs new file mode 100644 index 000000000..efbc958c7 --- /dev/null +++ b/runtime/js.rs @@ -0,0 +1,31 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. + +use deno_core::Snapshot; + +pub static CLI_SNAPSHOT: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/CLI_SNAPSHOT.bin")); + +pub fn deno_isolate_init() -> Snapshot { + debug!("Deno isolate init with snapshots."); + let data = CLI_SNAPSHOT; + Snapshot::Static(data) +} + +#[test] +fn cli_snapshot() { + let mut js_runtime = deno_core::JsRuntime::new(deno_core::RuntimeOptions { + startup_snapshot: Some(deno_isolate_init()), + ..Default::default() + }); + js_runtime + .execute( + "<anon>", + r#" + if (!(bootstrap.mainRuntime && bootstrap.workerRuntime)) { + throw Error("bad"); + } + console.log("we have console.log!!!"); + "#, + ) + .unwrap(); +} diff --git a/runtime/lib.rs b/runtime/lib.rs new file mode 100644 index 000000000..6745f3ec8 --- /dev/null +++ b/runtime/lib.rs @@ -0,0 +1,26 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. + +#![deny(warnings)] + +#[macro_use] +extern crate lazy_static; +#[macro_use] +extern crate log; + +pub use deno_crypto; +pub use deno_fetch; +pub use deno_web; + +pub mod colors; +pub mod errors; +pub mod fs_util; +pub mod http_util; +pub mod inspector; +pub mod js; +pub mod metrics; +pub mod ops; +pub mod permissions; +pub mod resolve_addr; +pub mod tokio_util; +pub mod web_worker; +pub mod worker; diff --git a/cli/metrics.rs b/runtime/metrics.rs index c70e0dab9..c70e0dab9 100644 --- a/cli/metrics.rs +++ b/runtime/metrics.rs diff --git a/cli/ops/crypto.rs b/runtime/ops/crypto.rs index a73843a33..a73843a33 100644 --- a/cli/ops/crypto.rs +++ b/runtime/ops/crypto.rs diff --git a/cli/ops/dispatch_minimal.rs b/runtime/ops/dispatch_minimal.rs index ae8fa819d..ae8fa819d 100644 --- a/cli/ops/dispatch_minimal.rs +++ b/runtime/ops/dispatch_minimal.rs diff --git a/cli/ops/fetch.rs b/runtime/ops/fetch.rs index 18e9e9c9f..0ef99f73d 100644 --- a/cli/ops/fetch.rs +++ b/runtime/ops/fetch.rs @@ -3,13 +3,16 @@ use crate::http_util; use crate::permissions::Permissions; use deno_fetch::reqwest; -pub fn init(rt: &mut deno_core::JsRuntime, maybe_ca_file: Option<&str>) { +pub fn init( + rt: &mut deno_core::JsRuntime, + user_agent: String, + maybe_ca_file: Option<&str>, +) { { let op_state = rt.op_state(); let mut state = op_state.borrow_mut(); state.put::<reqwest::Client>({ - http_util::create_http_client(http_util::get_user_agent(), maybe_ca_file) - .unwrap() + http_util::create_http_client(user_agent, maybe_ca_file).unwrap() }); } super::reg_json_async(rt, "op_fetch", deno_fetch::op_fetch::<Permissions>); diff --git a/cli/ops/fs.rs b/runtime/ops/fs.rs index 865c5bcca..865c5bcca 100644 --- a/cli/ops/fs.rs +++ b/runtime/ops/fs.rs diff --git a/cli/ops/fs_events.rs b/runtime/ops/fs_events.rs index 4832c915c..4832c915c 100644 --- a/cli/ops/fs_events.rs +++ b/runtime/ops/fs_events.rs diff --git a/cli/ops/io.rs b/runtime/ops/io.rs index 0f8af905a..0f8af905a 100644 --- a/cli/ops/io.rs +++ b/runtime/ops/io.rs diff --git a/runtime/ops/mod.rs b/runtime/ops/mod.rs new file mode 100644 index 000000000..a27122657 --- /dev/null +++ b/runtime/ops/mod.rs @@ -0,0 +1,89 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. + +mod dispatch_minimal; +pub use dispatch_minimal::MinimalOp; + +pub mod crypto; +pub mod fetch; +pub mod fs; +pub mod fs_events; +pub mod io; +pub mod net; +#[cfg(unix)] +mod net_unix; +pub mod os; +pub mod permissions; +pub mod plugin; +pub mod process; +pub mod runtime; +pub mod signal; +pub mod timers; +pub mod tls; +pub mod tty; +pub mod web_worker; +pub mod websocket; +pub mod worker_host; + +use crate::metrics::metrics_op; +use deno_core::error::AnyError; +use deno_core::json_op_async; +use deno_core::json_op_sync; +use deno_core::serde_json::Value; +use deno_core::BufVec; +use deno_core::JsRuntime; +use deno_core::OpState; +use deno_core::ZeroCopyBuf; +use std::cell::RefCell; +use std::future::Future; +use std::rc::Rc; + +pub fn reg_json_async<F, R>(rt: &mut JsRuntime, name: &'static str, op_fn: F) +where + F: Fn(Rc<RefCell<OpState>>, Value, BufVec) -> R + 'static, + R: Future<Output = Result<Value, AnyError>> + 'static, +{ + rt.register_op(name, metrics_op(json_op_async(op_fn))); +} + +pub fn reg_json_sync<F>(rt: &mut JsRuntime, name: &'static str, op_fn: F) +where + F: Fn(&mut OpState, Value, &mut [ZeroCopyBuf]) -> Result<Value, AnyError> + + 'static, +{ + rt.register_op(name, metrics_op(json_op_sync(op_fn))); +} + +/// `UnstableChecker` is a struct so it can be placed inside `GothamState`; +/// using type alias for a bool could work, but there's a high chance +/// that there might be another type alias pointing to a bool, which +/// would override previously used alias. +pub struct UnstableChecker { + pub unstable: bool, +} + +impl UnstableChecker { + /// Quits the process if the --unstable flag was not provided. + /// + /// This is intentionally a non-recoverable check so that people cannot probe + /// for unstable APIs from stable programs. + // NOTE(bartlomieju): keep in sync with `cli/program_state.rs` + pub fn check_unstable(&self, api_name: &str) { + if !self.unstable { + eprintln!( + "Unstable API '{}'. The --unstable flag must be provided.", + api_name + ); + std::process::exit(70); + } + } +} +/// Helper for checking unstable features. Used for sync ops. +pub fn check_unstable(state: &OpState, api_name: &str) { + state.borrow::<UnstableChecker>().check_unstable(api_name) +} + +/// Helper for checking unstable features. Used for async ops. +pub fn check_unstable2(state: &Rc<RefCell<OpState>>, api_name: &str) { + let state = state.borrow(); + state.borrow::<UnstableChecker>().check_unstable(api_name) +} diff --git a/cli/ops/net.rs b/runtime/ops/net.rs index 98ff83fc0..98ff83fc0 100644 --- a/cli/ops/net.rs +++ b/runtime/ops/net.rs diff --git a/cli/ops/net_unix.rs b/runtime/ops/net_unix.rs index 4c416a5a4..4c416a5a4 100644 --- a/cli/ops/net_unix.rs +++ b/runtime/ops/net_unix.rs diff --git a/cli/ops/os.rs b/runtime/ops/os.rs index 6fd404a23..6fd404a23 100644 --- a/cli/ops/os.rs +++ b/runtime/ops/os.rs diff --git a/cli/ops/permissions.rs b/runtime/ops/permissions.rs index 7474c0e37..7474c0e37 100644 --- a/cli/ops/permissions.rs +++ b/runtime/ops/permissions.rs diff --git a/cli/ops/plugin.rs b/runtime/ops/plugin.rs index 1f3669b6f..1f3669b6f 100644 --- a/cli/ops/plugin.rs +++ b/runtime/ops/plugin.rs diff --git a/cli/ops/process.rs b/runtime/ops/process.rs index 60a6d5095..67b3d0761 100644 --- a/cli/ops/process.rs +++ b/runtime/ops/process.rs @@ -2,7 +2,6 @@ use super::io::{std_file_resource, StreamResource, StreamResourceHolder}; use crate::permissions::Permissions; -use crate::signal::kill; use deno_core::error::bad_resource_id; use deno_core::error::type_error; use deno_core::error::AnyError; @@ -216,6 +215,61 @@ async fn op_run_status( })) } +#[cfg(not(unix))] +const SIGINT: i32 = 2; +#[cfg(not(unix))] +const SIGKILL: i32 = 9; +#[cfg(not(unix))] +const SIGTERM: i32 = 15; + +#[cfg(not(unix))] +use winapi::{ + shared::minwindef::DWORD, + um::{ + handleapi::CloseHandle, + processthreadsapi::{OpenProcess, TerminateProcess}, + winnt::PROCESS_TERMINATE, + }, +}; + +#[cfg(unix)] +pub fn kill(pid: i32, signo: i32) -> Result<(), AnyError> { + use nix::sys::signal::{kill as unix_kill, Signal}; + use nix::unistd::Pid; + use std::convert::TryFrom; + let sig = Signal::try_from(signo)?; + unix_kill(Pid::from_raw(pid), Option::Some(sig)).map_err(AnyError::from) +} + +#[cfg(not(unix))] +pub fn kill(pid: i32, signal: i32) -> Result<(), AnyError> { + use std::io::Error; + match signal { + SIGINT | SIGKILL | SIGTERM => { + if pid <= 0 { + return Err(type_error("unsupported pid")); + } + unsafe { + let handle = OpenProcess(PROCESS_TERMINATE, 0, pid as DWORD); + if handle.is_null() { + return Err(Error::last_os_error().into()); + } + if TerminateProcess(handle, 1) == 0 { + CloseHandle(handle); + return Err(Error::last_os_error().into()); + } + if CloseHandle(handle) == 0 { + return Err(Error::last_os_error().into()); + } + } + } + _ => { + return Err(type_error("unsupported signal")); + } + } + Ok(()) +} + #[derive(Deserialize)] struct KillArgs { pid: i32, diff --git a/cli/ops/runtime.rs b/runtime/ops/runtime.rs index cb3b53d53..cb3b53d53 100644 --- a/cli/ops/runtime.rs +++ b/runtime/ops/runtime.rs diff --git a/cli/ops/signal.rs b/runtime/ops/signal.rs index be6bc0a35..be6bc0a35 100644 --- a/cli/ops/signal.rs +++ b/runtime/ops/signal.rs diff --git a/cli/ops/timers.rs b/runtime/ops/timers.rs index 8037fd698..8037fd698 100644 --- a/cli/ops/timers.rs +++ b/runtime/ops/timers.rs diff --git a/cli/ops/tls.rs b/runtime/ops/tls.rs index 37fd8f206..37fd8f206 100644 --- a/cli/ops/tls.rs +++ b/runtime/ops/tls.rs diff --git a/cli/ops/tty.rs b/runtime/ops/tty.rs index be1d7d3e4..ad66bcf1a 100644 --- a/cli/ops/tty.rs +++ b/runtime/ops/tty.rs @@ -4,7 +4,6 @@ use super::io::std_file_resource; use super::io::StreamResource; use super::io::StreamResourceHolder; use deno_core::error::bad_resource_id; -use deno_core::error::last_os_error; use deno_core::error::not_supported; use deno_core::error::resource_unavailable; use deno_core::error::AnyError; @@ -15,6 +14,7 @@ use deno_core::OpState; use deno_core::ZeroCopyBuf; use serde::Deserialize; use serde::Serialize; +use std::io::Error; #[cfg(unix)] use nix::sys::termios; @@ -39,7 +39,7 @@ fn get_windows_handle( let handle = f.as_raw_handle(); if handle == handleapi::INVALID_HANDLE_VALUE { - return Err(last_os_error()); + return Err(Error::last_os_error().into()); } else if handle.is_null() { return Err(custom_error("ReferenceError", "null handle")); } @@ -131,7 +131,7 @@ fn op_set_raw( }; if handle == handleapi::INVALID_HANDLE_VALUE { - return Err(last_os_error()); + return Err(Error::last_os_error().into()); } else if handle.is_null() { return Err(custom_error("ReferenceError", "null handle")); } @@ -139,7 +139,7 @@ fn op_set_raw( if unsafe { consoleapi::GetConsoleMode(handle, &mut original_mode) } == FALSE { - return Err(last_os_error()); + return Err(Error::last_os_error().into()); } let new_mode = if is_raw { original_mode & !RAW_MODE_MASK @@ -147,7 +147,7 @@ fn op_set_raw( original_mode | RAW_MODE_MASK }; if unsafe { consoleapi::SetConsoleMode(handle, new_mode) } == FALSE { - return Err(last_os_error()); + return Err(Error::last_os_error().into()); } Ok(json!({})) @@ -298,7 +298,7 @@ fn op_console_size( &mut bufinfo, ) == 0 { - return Err(last_os_error()); + return Err(Error::last_os_error().into()); } Ok(ConsoleSize { @@ -316,7 +316,7 @@ fn op_console_size( unsafe { let mut size: libc::winsize = std::mem::zeroed(); if libc::ioctl(fd, libc::TIOCGWINSZ, &mut size as *mut _) != 0 { - return Err(last_os_error()); + return Err(Error::last_os_error().into()); } // TODO (caspervonb) return a tuple instead diff --git a/cli/ops/web_worker.rs b/runtime/ops/web_worker.rs index d88330a04..d88330a04 100644 --- a/cli/ops/web_worker.rs +++ b/runtime/ops/web_worker.rs diff --git a/cli/ops/websocket.rs b/runtime/ops/websocket.rs index a8c591a33..a8c591a33 100644 --- a/cli/ops/websocket.rs +++ b/runtime/ops/websocket.rs diff --git a/cli/ops/worker_host.rs b/runtime/ops/worker_host.rs index 871e4b9fe..871e4b9fe 100644 --- a/cli/ops/worker_host.rs +++ b/runtime/ops/worker_host.rs diff --git a/cli/permissions.rs b/runtime/permissions.rs index cc3ce8242..88f9c7179 100644 --- a/cli/permissions.rs +++ b/runtime/permissions.rs @@ -1,7 +1,6 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. use crate::colors; -use crate::flags::Flags; use crate::fs_util::resolve_from_cwd; use deno_core::error::custom_error; use deno_core::error::uri_error; @@ -86,8 +85,22 @@ fn resolve_fs_allowlist(allowlist: &[PathBuf]) -> HashSet<PathBuf> { .collect() } +#[derive(Clone, Debug, PartialEq, Default)] +pub struct PermissionsOptions { + pub allow_env: bool, + pub allow_hrtime: bool, + pub allow_net: bool, + pub allow_plugin: bool, + pub allow_read: bool, + pub allow_run: bool, + pub allow_write: bool, + pub net_allowlist: Vec<String>, + pub read_allowlist: Vec<PathBuf>, + pub write_allowlist: Vec<PathBuf>, +} + impl Permissions { - pub fn from_flags(flags: &Flags) -> Self { + pub fn from_options(opts: &PermissionsOptions) -> Self { fn state_from_flag_bool(flag: bool) -> PermissionState { if flag { PermissionState::Granted @@ -97,24 +110,24 @@ impl Permissions { } Self { read: UnaryPermission::<PathBuf> { - global_state: state_from_flag_bool(flags.allow_read), - granted_list: resolve_fs_allowlist(&flags.read_allowlist), + global_state: state_from_flag_bool(opts.allow_read), + granted_list: resolve_fs_allowlist(&opts.read_allowlist), ..Default::default() }, write: UnaryPermission::<PathBuf> { - global_state: state_from_flag_bool(flags.allow_write), - granted_list: resolve_fs_allowlist(&flags.write_allowlist), + global_state: state_from_flag_bool(opts.allow_write), + granted_list: resolve_fs_allowlist(&opts.write_allowlist), ..Default::default() }, net: UnaryPermission::<String> { - global_state: state_from_flag_bool(flags.allow_net), - granted_list: flags.net_allowlist.iter().cloned().collect(), + global_state: state_from_flag_bool(opts.allow_net), + granted_list: opts.net_allowlist.iter().cloned().collect(), ..Default::default() }, - env: state_from_flag_bool(flags.allow_env), - run: state_from_flag_bool(flags.allow_run), - plugin: state_from_flag_bool(flags.allow_plugin), - hrtime: state_from_flag_bool(flags.allow_hrtime), + env: state_from_flag_bool(opts.allow_env), + run: state_from_flag_bool(opts.allow_run), + plugin: state_from_flag_bool(opts.allow_plugin), + hrtime: state_from_flag_bool(opts.allow_hrtime), } } @@ -693,7 +706,7 @@ mod tests { PathBuf::from("/b/c"), ]; - let perms = Permissions::from_flags(&Flags { + let perms = Permissions::from_options(&PermissionsOptions { read_allowlist: allowlist.clone(), write_allowlist: allowlist, ..Default::default() @@ -748,7 +761,7 @@ mod tests { #[test] fn test_check_net() { - let perms = Permissions::from_flags(&Flags { + let perms = Permissions::from_options(&PermissionsOptions { net_allowlist: svec![ "localhost", "deno.land", @@ -839,7 +852,7 @@ mod tests { } else { vec![PathBuf::from("/a")] }; - let perms = Permissions::from_flags(&Flags { + let perms = Permissions::from_options(&PermissionsOptions { read_allowlist, net_allowlist: svec!["localhost"], ..Default::default() diff --git a/cli/resolve_addr.rs b/runtime/resolve_addr.rs index c3dc52f8f..c3dc52f8f 100644 --- a/cli/resolve_addr.rs +++ b/runtime/resolve_addr.rs diff --git a/cli/rt/00_bootstrap_namespace.js b/runtime/rt/00_bootstrap_namespace.js index 514cbe3f0..514cbe3f0 100644 --- a/cli/rt/00_bootstrap_namespace.js +++ b/runtime/rt/00_bootstrap_namespace.js diff --git a/cli/rt/01_build.js b/runtime/rt/01_build.js index 7c1dc817e..7c1dc817e 100644 --- a/cli/rt/01_build.js +++ b/runtime/rt/01_build.js diff --git a/cli/rt/01_colors.js b/runtime/rt/01_colors.js index 39e4a7a18..39e4a7a18 100644 --- a/cli/rt/01_colors.js +++ b/runtime/rt/01_colors.js diff --git a/cli/rt/01_errors.js b/runtime/rt/01_errors.js index d5933069b..d5933069b 100644 --- a/cli/rt/01_errors.js +++ b/runtime/rt/01_errors.js diff --git a/cli/rt/01_internals.js b/runtime/rt/01_internals.js index eee9eeaf7..eee9eeaf7 100644 --- a/cli/rt/01_internals.js +++ b/runtime/rt/01_internals.js diff --git a/cli/rt/01_version.js b/runtime/rt/01_version.js index 325e1156f..325e1156f 100644 --- a/cli/rt/01_version.js +++ b/runtime/rt/01_version.js diff --git a/cli/rt/01_web_util.js b/runtime/rt/01_web_util.js index a9573a71d..a9573a71d 100644 --- a/cli/rt/01_web_util.js +++ b/runtime/rt/01_web_util.js diff --git a/cli/rt/02_console.js b/runtime/rt/02_console.js index 971837bd6..971837bd6 100644 --- a/cli/rt/02_console.js +++ b/runtime/rt/02_console.js diff --git a/cli/rt/06_util.js b/runtime/rt/06_util.js index f4804c519..f4804c519 100644 --- a/cli/rt/06_util.js +++ b/runtime/rt/06_util.js diff --git a/cli/rt/10_dispatch_minimal.js b/runtime/rt/10_dispatch_minimal.js index dceb23e5f..dceb23e5f 100644 --- a/cli/rt/10_dispatch_minimal.js +++ b/runtime/rt/10_dispatch_minimal.js diff --git a/cli/rt/11_timers.js b/runtime/rt/11_timers.js index 5a59844a3..5a59844a3 100644 --- a/cli/rt/11_timers.js +++ b/runtime/rt/11_timers.js diff --git a/cli/rt/11_workers.js b/runtime/rt/11_workers.js index 62210dfae..62210dfae 100644 --- a/cli/rt/11_workers.js +++ b/runtime/rt/11_workers.js diff --git a/cli/rt/12_io.js b/runtime/rt/12_io.js index 006d51cdd..006d51cdd 100644 --- a/cli/rt/12_io.js +++ b/runtime/rt/12_io.js diff --git a/cli/rt/13_buffer.js b/runtime/rt/13_buffer.js index e06e2138b..e06e2138b 100644 --- a/cli/rt/13_buffer.js +++ b/runtime/rt/13_buffer.js diff --git a/cli/rt/27_websocket.js b/runtime/rt/27_websocket.js index 60428c24d..60428c24d 100644 --- a/cli/rt/27_websocket.js +++ b/runtime/rt/27_websocket.js diff --git a/cli/rt/30_files.js b/runtime/rt/30_files.js index 679b184fd..679b184fd 100644 --- a/cli/rt/30_files.js +++ b/runtime/rt/30_files.js diff --git a/cli/rt/30_fs.js b/runtime/rt/30_fs.js index 33fab01e4..33fab01e4 100644 --- a/cli/rt/30_fs.js +++ b/runtime/rt/30_fs.js diff --git a/cli/rt/30_metrics.js b/runtime/rt/30_metrics.js index d44a629cb..d44a629cb 100644 --- a/cli/rt/30_metrics.js +++ b/runtime/rt/30_metrics.js diff --git a/cli/rt/30_net.js b/runtime/rt/30_net.js index 9a71f0693..9a71f0693 100644 --- a/cli/rt/30_net.js +++ b/runtime/rt/30_net.js diff --git a/cli/rt/30_os.js b/runtime/rt/30_os.js index ebc4e8916..ebc4e8916 100644 --- a/cli/rt/30_os.js +++ b/runtime/rt/30_os.js diff --git a/cli/rt/40_compiler_api.js b/runtime/rt/40_compiler_api.js index ea963b67b..ea963b67b 100644 --- a/cli/rt/40_compiler_api.js +++ b/runtime/rt/40_compiler_api.js diff --git a/cli/rt/40_diagnostics.js b/runtime/rt/40_diagnostics.js index 2b7457853..2b7457853 100644 --- a/cli/rt/40_diagnostics.js +++ b/runtime/rt/40_diagnostics.js diff --git a/cli/rt/40_error_stack.js b/runtime/rt/40_error_stack.js index da2ee51f3..da2ee51f3 100644 --- a/cli/rt/40_error_stack.js +++ b/runtime/rt/40_error_stack.js diff --git a/cli/rt/40_fs_events.js b/runtime/rt/40_fs_events.js index a36adecba..a36adecba 100644 --- a/cli/rt/40_fs_events.js +++ b/runtime/rt/40_fs_events.js diff --git a/cli/rt/40_net_unstable.js b/runtime/rt/40_net_unstable.js index fcc899a30..fcc899a30 100644 --- a/cli/rt/40_net_unstable.js +++ b/runtime/rt/40_net_unstable.js diff --git a/cli/rt/40_performance.js b/runtime/rt/40_performance.js index 0a63dc704..0a63dc704 100644 --- a/cli/rt/40_performance.js +++ b/runtime/rt/40_performance.js diff --git a/cli/rt/40_permissions.js b/runtime/rt/40_permissions.js index 50d471b6a..50d471b6a 100644 --- a/cli/rt/40_permissions.js +++ b/runtime/rt/40_permissions.js diff --git a/cli/rt/40_plugins.js b/runtime/rt/40_plugins.js index f5aefd400..f5aefd400 100644 --- a/cli/rt/40_plugins.js +++ b/runtime/rt/40_plugins.js diff --git a/cli/rt/40_process.js b/runtime/rt/40_process.js index b46a1aead..b46a1aead 100644 --- a/cli/rt/40_process.js +++ b/runtime/rt/40_process.js diff --git a/cli/rt/40_read_file.js b/runtime/rt/40_read_file.js index 9a36f335b..9a36f335b 100644 --- a/cli/rt/40_read_file.js +++ b/runtime/rt/40_read_file.js diff --git a/cli/rt/40_signals.js b/runtime/rt/40_signals.js index 739c963fd..739c963fd 100644 --- a/cli/rt/40_signals.js +++ b/runtime/rt/40_signals.js diff --git a/cli/rt/40_testing.js b/runtime/rt/40_testing.js index 082d17fe0..082d17fe0 100644 --- a/cli/rt/40_testing.js +++ b/runtime/rt/40_testing.js diff --git a/cli/rt/40_tls.js b/runtime/rt/40_tls.js index d66e0bd01..d66e0bd01 100644 --- a/cli/rt/40_tls.js +++ b/runtime/rt/40_tls.js diff --git a/cli/rt/40_tty.js b/runtime/rt/40_tty.js index 598d33237..598d33237 100644 --- a/cli/rt/40_tty.js +++ b/runtime/rt/40_tty.js diff --git a/cli/rt/40_write_file.js b/runtime/rt/40_write_file.js index 7a9cb1f40..7a9cb1f40 100644 --- a/cli/rt/40_write_file.js +++ b/runtime/rt/40_write_file.js diff --git a/cli/rt/41_prompt.js b/runtime/rt/41_prompt.js index ec294668b..ec294668b 100644 --- a/cli/rt/41_prompt.js +++ b/runtime/rt/41_prompt.js diff --git a/cli/rt/90_deno_ns.js b/runtime/rt/90_deno_ns.js index 9188788ec..9188788ec 100644 --- a/cli/rt/90_deno_ns.js +++ b/runtime/rt/90_deno_ns.js diff --git a/cli/rt/99_main.js b/runtime/rt/99_main.js index f38d51936..f38d51936 100644 --- a/cli/rt/99_main.js +++ b/runtime/rt/99_main.js diff --git a/cli/rt/README.md b/runtime/rt/README.md index b17fa22e5..b17fa22e5 100644 --- a/cli/rt/README.md +++ b/runtime/rt/README.md diff --git a/runtime/tokio_util.rs b/runtime/tokio_util.rs new file mode 100644 index 000000000..b25a2994f --- /dev/null +++ b/runtime/tokio_util.rs @@ -0,0 +1,25 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. + +pub fn create_basic_runtime() -> tokio::runtime::Runtime { + tokio::runtime::Builder::new() + .basic_scheduler() + .enable_io() + .enable_time() + // This limits the number of threads for blocking operations (like for + // synchronous fs ops) or CPU bound tasks like when we run dprint in + // parallel for deno fmt. + // The default value is 512, which is an unhelpfully large thread pool. We + // don't ever want to have more than a couple dozen threads. + .max_threads(32) + .build() + .unwrap() +} + +// TODO(ry) rename to run_local ? +pub fn run_basic<F, R>(future: F) -> R +where + F: std::future::Future<Output = R>, +{ + let mut rt = create_basic_runtime(); + rt.block_on(future) +} diff --git a/cli/web_worker.rs b/runtime/web_worker.rs index 18d391580..db97e3604 100644 --- a/cli/web_worker.rs +++ b/runtime/web_worker.rs @@ -18,6 +18,7 @@ use deno_core::serde_json; use deno_core::serde_json::json; use deno_core::url::Url; use deno_core::v8; +use deno_core::GetErrorClassFn; use deno_core::JsErrorCreateFn; use deno_core::JsRuntime; use deno_core::ModuleLoader; @@ -122,8 +123,8 @@ pub struct WebWorker { // Following fields are pub because they are accessed // when creating a new WebWorker instance. pub(crate) internal_channels: WorkerChannelsInternal, - pub(crate) js_runtime: JsRuntime, - pub(crate) name: String, + pub js_runtime: JsRuntime, + pub name: String, waker: AtomicWaker, event_loop_idle: bool, terminate_rx: mpsc::Receiver<()>, @@ -152,6 +153,7 @@ pub struct WebWorkerOptions { pub ts_version: String, /// Sets `Deno.noColor` in JS runtime. pub no_color: bool, + pub get_error_class_fn: Option<GetErrorClassFn>, } impl WebWorker { @@ -166,7 +168,7 @@ impl WebWorker { module_loader: Some(options.module_loader.clone()), startup_snapshot: Some(js::deno_isolate_init()), js_error_create_fn: options.js_error_create_fn.clone(), - get_error_class_fn: Some(&crate::errors::get_error_class_name), + get_error_class_fn: options.get_error_class_fn, ..Default::default() }); @@ -214,7 +216,11 @@ impl WebWorker { ops::web_worker::init(js_runtime, sender.clone(), handle); ops::runtime::init(js_runtime, main_module); - ops::fetch::init(js_runtime, options.ca_filepath.as_deref()); + ops::fetch::init( + js_runtime, + options.user_agent.clone(), + options.ca_filepath.as_deref(), + ); ops::timers::init(js_runtime); ops::worker_host::init( js_runtime, @@ -488,6 +494,7 @@ mod tests { runtime_version: "x".to_string(), ts_version: "x".to_string(), no_color: true, + get_error_class_fn: None, }; let mut worker = WebWorker::from_options( diff --git a/cli/worker.rs b/runtime/worker.rs index d1238df41..a0e63afad 100644 --- a/cli/worker.rs +++ b/runtime/worker.rs @@ -13,6 +13,7 @@ use deno_core::futures::future::FutureExt; use deno_core::serde_json; use deno_core::serde_json::json; use deno_core::url::Url; +use deno_core::GetErrorClassFn; use deno_core::JsErrorCreateFn; use deno_core::JsRuntime; use deno_core::ModuleId; @@ -61,6 +62,7 @@ pub struct WorkerOptions { pub ts_version: String, /// Sets `Deno.noColor` in JS runtime. pub no_color: bool, + pub get_error_class_fn: Option<GetErrorClassFn>, } impl MainWorker { @@ -73,7 +75,7 @@ impl MainWorker { module_loader: Some(options.module_loader.clone()), startup_snapshot: Some(js::deno_isolate_init()), js_error_create_fn: options.js_error_create_fn.clone(), - get_error_class_fn: Some(&crate::errors::get_error_class_name), + get_error_class_fn: options.get_error_class_fn, ..Default::default() }); @@ -108,7 +110,11 @@ impl MainWorker { } ops::runtime::init(js_runtime, main_module); - ops::fetch::init(js_runtime, options.ca_filepath.as_deref()); + ops::fetch::init( + js_runtime, + options.user_agent.clone(), + options.ca_filepath.as_deref(), + ); ops::timers::init(js_runtime); ops::worker_host::init( js_runtime, @@ -274,6 +280,7 @@ mod tests { runtime_version: "x".to_string(), ts_version: "x".to_string(), no_color: true, + get_error_class_fn: None, }; MainWorker::from_options(main_module, permissions, &options) |