1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-21 04:52:26 -05:00

refactor: deno_runtime crate (#8640)

This commit moves Deno JS runtime, ops, permissions and
inspector implementation to new "deno_runtime" crate located
in "runtime/" directory.

Details in "runtime/README.md".

Co-authored-by: Ryan Dahl <ry@tinyclouds.org>
This commit is contained in:
Bartek Iwańczuk 2020-12-13 19:45:53 +01:00 committed by GitHub
parent 84ef9bd21f
commit 2e74f164b6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
99 changed files with 1127 additions and 458 deletions

48
Cargo.lock generated
View file

@ -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",
]
@ -582,6 +578,48 @@ dependencies = [
"swc_ecmascript",
]
[[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"

View file

@ -4,6 +4,7 @@
members = [
"cli",
"core",
"runtime",
"test_plugin",
"test_util",
"op_crates/fetch",

View file

@ -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"] }

View file

@ -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);

View file

@ -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: &notify::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: &regex::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);
})

View file

@ -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;

View file

@ -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();

View file

@ -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;

View 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,37 +14,12 @@ 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;
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();
}
#[test]
fn compiler_snapshot() {
let mut js_runtime = deno_core::JsRuntime::new(deno_core::RuntimeOptions {

View file

@ -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 =

View file

@ -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;

View file

@ -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)
}

View file

@ -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!({

View file

@ -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;

View file

@ -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(())
}

View file

@ -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;

View file

@ -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);

View file

@ -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 {

View file

@ -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;

View file

@ -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;

View file

@ -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)
}

74
runtime/Cargo.toml Normal file
View file

@ -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" }

44
runtime/README.md Normal file
View file

@ -0,0 +1,44 @@
# `deno_runtime` crate
[![crates](https://img.shields.io/crates/v/deno_runtime.svg)](https://crates.io/crates/deno_runtime)
[![docs](https://docs.rs/deno_runtime/badge.svg)](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.

81
runtime/build.rs Normal file
View file

@ -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
}

130
runtime/colors.rs Normal file
View file

@ -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)
}

209
runtime/errors.rs Normal file
View file

@ -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: &notify::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: &regex::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)()
})
}

View file

@ -0,0 +1,2 @@
console.log("Hello world!");
console.log(Deno);

View file

@ -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(())
}

80
runtime/fs_util.rs Normal file
View file

@ -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);
}
}

46
runtime/http_util.rs Normal file
View file

@ -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();
}
}

31
runtime/js.rs Normal file
View file

@ -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();
}

26
runtime/lib.rs Normal file
View file

@ -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;

View file

@ -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>);

89
runtime/ops/mod.rs Normal file
View file

@ -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)
}

View file

@ -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,

View file

@ -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

View file

@ -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()

25
runtime/tokio_util.rs Normal file
View file

@ -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)
}

View file

@ -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(

View file

@ -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)