From 27f4aeb92469660fdd78a89a7b2902c08a23ca4a Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Tue, 18 Aug 2020 18:30:13 +0200 Subject: [PATCH] Make Rc/Arc wrapper around State/GlobalState visible (#7104) --- cli/file_fetcher.rs | 2 +- cli/global_state.rs | 57 +++------- cli/http_util.rs | 18 +-- cli/main.rs | 27 ++--- cli/module_graph.rs | 2 +- cli/ops/compiler.rs | 3 +- cli/ops/errors.rs | 9 +- cli/ops/fetch.rs | 14 ++- cli/ops/fs.rs | 52 ++++----- cli/ops/fs_events.rs | 7 +- cli/ops/idna.rs | 5 +- cli/ops/io.rs | 7 +- cli/ops/net.rs | 17 +-- cli/ops/os.rs | 21 ++-- cli/ops/permissions.rs | 18 ++- cli/ops/plugin.rs | 4 +- cli/ops/process.rs | 9 +- cli/ops/random.rs | 9 +- cli/ops/repl.rs | 9 +- cli/ops/resources.rs | 7 +- cli/ops/runtime.rs | 15 ++- cli/ops/runtime_compiler.rs | 23 ++-- cli/ops/signal.rs | 15 +-- cli/ops/timers.rs | 19 ++-- cli/ops/tls.rs | 11 +- cli/ops/tty.rs | 9 +- cli/ops/web_worker.rs | 3 +- cli/ops/worker_host.rs | 64 +++++------ cli/state.rs | 214 +++++++++++++++--------------------- cli/tokio_util.rs | 2 +- cli/tsc.rs | 50 ++++----- cli/web_worker.rs | 8 +- cli/worker.rs | 68 +++++------- 33 files changed, 368 insertions(+), 430 deletions(-) diff --git a/cli/file_fetcher.rs b/cli/file_fetcher.rs index 38b7008877..c703bfc272 100644 --- a/cli/file_fetcher.rs +++ b/cli/file_fetcher.rs @@ -121,7 +121,7 @@ impl SourceFileFetcher { cache_blocklist: Vec, no_remote: bool, cached_only: bool, - ca_file: Option, + ca_file: Option<&str>, ) -> Result { let file_fetcher = Self { http_cache, diff --git a/cli/global_state.rs b/cli/global_state.rs index a723bdd2fe..a1d4af86c6 100644 --- a/cli/global_state.rs +++ b/cli/global_state.rs @@ -17,20 +17,15 @@ use crate::tsc::TsCompiler; use deno_core::ErrBox; use deno_core::ModuleSpecifier; use std::env; -use std::ops::Deref; use std::sync::atomic::AtomicUsize; use std::sync::Arc; use std::sync::Mutex; use tokio::sync::Mutex as AsyncMutex; -/// Holds state of the program and can be accessed by V8 isolate. -#[derive(Clone)] -pub struct GlobalState(Arc); - /// This structure represents state of single "deno" program. /// /// It is shared by all created workers (thus V8 isolates). -pub struct GlobalStateInner { +pub struct GlobalState { /// Flags parsed from `argv` contents. pub flags: flags::Flags, /// Permissions parsed from `flags`. @@ -44,23 +39,13 @@ pub struct GlobalStateInner { compile_lock: AsyncMutex<()>, } -impl Deref for GlobalState { - type Target = GlobalStateInner; - fn deref(&self) -> &Self::Target { - &self.0 - } -} - impl GlobalState { - pub fn new(flags: flags::Flags) -> Result { + pub fn new(flags: flags::Flags) -> Result, ErrBox> { let custom_root = env::var("DENO_DIR").map(String::into).ok(); let dir = deno_dir::DenoDir::new(custom_root)?; let deps_cache_location = dir.root.join("deps"); let http_cache = http_cache::HttpCache::new(&deps_cache_location); - let ca_file = flags - .ca_file - .clone() - .or_else(|| env::var("DENO_CERT").map(String::into).ok()); + let ca_file = flags.ca_file.clone().or_else(|| env::var("DENO_CERT").ok()); let file_fetcher = SourceFileFetcher::new( http_cache, @@ -68,7 +53,7 @@ impl GlobalState { flags.cache_blocklist.clone(), flags.no_remote, flags.cached_only, - ca_file, + ca_file.as_deref(), )?; let ts_compiler = TsCompiler::new( @@ -95,7 +80,7 @@ impl GlobalState { } }; - let inner = GlobalStateInner { + let global_state = GlobalState { dir, permissions: Permissions::from_flags(&flags), flags, @@ -106,7 +91,7 @@ impl GlobalState { compiler_starts: AtomicUsize::new(0), compile_lock: AsyncMutex::new(()), }; - Ok(GlobalState(Arc::new(inner))) + Ok(Arc::new(global_state)) } /// This function is called when new module load is @@ -114,7 +99,7 @@ impl GlobalState { /// all dependencies and if it is required then also perform TS typecheck /// and traspilation. pub async fn prepare_module_load( - &self, + self: &Arc, module_specifier: ModuleSpecifier, maybe_referrer: Option, target_lib: TargetLib, @@ -178,14 +163,7 @@ impl GlobalState { } else { self .ts_compiler - .compile( - self.clone(), - &out, - target_lib, - permissions, - module_graph, - allow_js, - ) + .compile(self, &out, target_lib, permissions, module_graph, allow_js) .await?; } } @@ -210,7 +188,6 @@ impl GlobalState { module_specifier: ModuleSpecifier, _maybe_referrer: Option, ) -> Result { - let state1 = self.clone(); let module_specifier = module_specifier.clone(); let out = self @@ -232,7 +209,7 @@ impl GlobalState { }; let compiled_module = if was_compiled { - match state1.ts_compiler.get_compiled_module(&out.url) { + match self.ts_compiler.get_compiled_module(&out.url) { Ok(module) => module, Err(e) => { let msg = format!( @@ -264,16 +241,12 @@ impl GlobalState { pub fn mock( argv: Vec, maybe_flags: Option, - ) -> GlobalState { - if let Some(in_flags) = maybe_flags { - GlobalState::new(flags::Flags { argv, ..in_flags }).unwrap() - } else { - GlobalState::new(flags::Flags { - argv, - ..flags::Flags::default() - }) - .unwrap() - } + ) -> Arc { + GlobalState::new(flags::Flags { + argv, + ..maybe_flags.unwrap_or_default() + }) + .unwrap() } } diff --git a/cli/http_util.rs b/cli/http_util.rs index 531339b5d1..bf302f7b22 100644 --- a/cli/http_util.rs +++ b/cli/http_util.rs @@ -26,7 +26,7 @@ use url::Url; /// Create new instance of async reqwest::Client. This client supports /// proxies and doesn't follow redirects. -pub fn create_http_client(ca_file: Option) -> Result { +pub fn create_http_client(ca_file: Option<&str>) -> Result { let mut headers = HeaderMap::new(); headers.insert( USER_AGENT, @@ -397,12 +397,12 @@ mod tests { let url = Url::parse("https://localhost:5545/cli/tests/fixture.json").unwrap(); - let client = create_http_client(Some(String::from( + let client = create_http_client(Some( test_util::root_path() .join("std/http/testdata/tls/RootCA.pem") .to_str() .unwrap(), - ))) + )) .unwrap(); let result = fetch_once(client, &url, None).await; if let Ok(FetchOnceResult::Code(body, headers)) = result { @@ -423,12 +423,12 @@ mod tests { "https://localhost:5545/cli/tests/053_import_compression/gziped", ) .unwrap(); - let client = create_http_client(Some(String::from( + let client = create_http_client(Some( test_util::root_path() .join("std/http/testdata/tls/RootCA.pem") .to_str() .unwrap(), - ))) + )) .unwrap(); let result = fetch_once(client, &url, None).await; if let Ok(FetchOnceResult::Code(body, headers)) = result { @@ -448,12 +448,12 @@ mod tests { async fn test_fetch_with_cafile_with_etag() { let _http_server_guard = test_util::http_server(); let url = Url::parse("https://localhost:5545/etag_script.ts").unwrap(); - let client = create_http_client(Some(String::from( + let client = create_http_client(Some( test_util::root_path() .join("std/http/testdata/tls/RootCA.pem") .to_str() .unwrap(), - ))) + )) .unwrap(); let result = fetch_once(client.clone(), &url, None).await; if let Ok(FetchOnceResult::Code(body, headers)) = result { @@ -482,12 +482,12 @@ mod tests { "https://localhost:5545/cli/tests/053_import_compression/brotli", ) .unwrap(); - let client = create_http_client(Some(String::from( + let client = create_http_client(Some( test_util::root_path() .join("std/http/testdata/tls/RootCA.pem") .to_str() .unwrap(), - ))) + )) .unwrap(); let result = fetch_once(client, &url, None).await; if let Ok(FetchOnceResult::Code(body, headers)) = result { diff --git a/cli/main.rs b/cli/main.rs index b5eb0b745a..c1774f5b90 100644 --- a/cli/main.rs +++ b/cli/main.rs @@ -99,6 +99,7 @@ use std::io::Write; use std::iter::once; use std::path::PathBuf; use std::pin::Pin; +use std::sync::Arc; use upgrade::upgrade_command; use url::Url; @@ -151,7 +152,10 @@ where serde_json::to_writer_pretty(writer, value).map_err(ErrBox::from) } -fn print_cache_info(state: &GlobalState, json: bool) -> Result<(), ErrBox> { +fn print_cache_info( + state: &Arc, + json: bool, +) -> Result<(), ErrBox> { let deno_dir = &state.dir.root; let modules_cache = &state.file_fetcher.http_cache.location; let typescript_cache = &state.dir.gen_cache.location; @@ -193,7 +197,7 @@ async fn print_file_info( module_specifier: ModuleSpecifier, json: bool, ) -> Result<(), ErrBox> { - let global_state = worker.state.borrow().global_state.clone(); + let global_state = worker.state.global_state.clone(); let out = global_state .file_fetcher @@ -316,7 +320,7 @@ async fn info_command( print_cache_info(&global_state, json) } else { let main_module = ModuleSpecifier::resolve_url_or_path(&file.unwrap())?; - let mut worker = MainWorker::create(global_state, main_module.clone())?; + let mut worker = MainWorker::create(&global_state, main_module.clone())?; worker.preload_module(&main_module).await?; print_file_info(&worker, main_module.clone(), json).await } @@ -335,7 +339,7 @@ async fn install_command( fetch_flags.reload = true; let global_state = GlobalState::new(fetch_flags)?; let main_module = ModuleSpecifier::resolve_url_or_path(&module_url)?; - let mut worker = MainWorker::create(global_state, main_module.clone())?; + let mut worker = MainWorker::create(&global_state, main_module.clone())?; worker.preload_module(&main_module).await?; installer::install(flags, &module_url, args, name, root, force) .map_err(ErrBox::from) @@ -364,8 +368,7 @@ async fn cache_command(flags: Flags, files: Vec) -> Result<(), ErrBox> { let main_module = ModuleSpecifier::resolve_url_or_path("./__$deno$fetch.ts").unwrap(); let global_state = GlobalState::new(flags)?; - let mut worker = - MainWorker::create(global_state.clone(), main_module.clone())?; + let mut worker = MainWorker::create(&global_state, main_module.clone())?; for file in files { let specifier = ModuleSpecifier::resolve_url_or_path(&file)?; @@ -385,8 +388,7 @@ async fn eval_command( let main_module = ModuleSpecifier::resolve_url_or_path("./__$deno$eval.ts").unwrap(); let global_state = GlobalState::new(flags)?; - let mut worker = - MainWorker::create(global_state.clone(), main_module.clone())?; + let mut worker = MainWorker::create(&global_state, main_module.clone())?; let main_module_url = main_module.as_url().to_owned(); // Create a dummy source file. let source_code = if print { @@ -438,7 +440,7 @@ async fn bundle_command( let output = global_state .ts_compiler - .bundle(global_state.clone(), module_specifier) + .bundle(&global_state, module_specifier) .await?; debug!(">>>>> bundle END"); @@ -566,7 +568,7 @@ async fn run_repl(flags: Flags) -> Result<(), ErrBox> { let main_module = ModuleSpecifier::resolve_url_or_path("./__$deno$repl.ts").unwrap(); let global_state = GlobalState::new(flags)?; - let mut worker = MainWorker::create(global_state, main_module)?; + let mut worker = MainWorker::create(&global_state, main_module)?; loop { (&mut *worker).await?; } @@ -580,7 +582,7 @@ async fn run_command(flags: Flags, script: String) -> Result<(), ErrBox> { ModuleSpecifier::resolve_url_or_path("./__$deno$stdin.ts").unwrap() }; let mut worker = - MainWorker::create(global_state.clone(), main_module.clone())?; + MainWorker::create(&global_state.clone(), main_module.clone())?; if script == "-" { let mut source = Vec::new(); std::io::stdin().read_to_end(&mut source)?; @@ -636,8 +638,7 @@ async fn test_command( test_runner::render_test_file(test_modules, fail_fast, quiet, filter); let main_module = ModuleSpecifier::resolve_url(&test_file_url.to_string()).unwrap(); - let mut worker = - MainWorker::create(global_state.clone(), main_module.clone())?; + let mut worker = MainWorker::create(&global_state, main_module.clone())?; // Create a dummy source file. let source_file = SourceFile { filename: test_file_url.to_file_path().unwrap(), diff --git a/cli/module_graph.rs b/cli/module_graph.rs index 9214fad33b..3c07acd3b4 100644 --- a/cli/module_graph.rs +++ b/cli/module_graph.rs @@ -582,7 +582,7 @@ impl ModuleGraphLoader { #[cfg(test)] mod tests { use super::*; - use crate::GlobalState; + use crate::global_state::GlobalState; async fn build_graph( module_specifier: &ModuleSpecifier, diff --git a/cli/ops/compiler.rs b/cli/ops/compiler.rs index d413698553..7ad4aece3c 100644 --- a/cli/ops/compiler.rs +++ b/cli/ops/compiler.rs @@ -6,12 +6,13 @@ use crate::state::State; use deno_core::CoreIsolate; use deno_core::CoreIsolateState; use deno_core::ZeroCopyBuf; +use std::rc::Rc; use std::sync::Arc; use std::sync::Mutex; pub fn init( i: &mut CoreIsolate, - _s: &State, + _s: &Rc, response: Arc>>, ) { let custom_assets = std::collections::HashMap::new(); diff --git a/cli/ops/errors.rs b/cli/ops/errors.rs index ade125b1a1..02295d7f81 100644 --- a/cli/ops/errors.rs +++ b/cli/ops/errors.rs @@ -8,8 +8,9 @@ use crate::state::State; use deno_core::CoreIsolate; use deno_core::ZeroCopyBuf; use std::collections::HashMap; +use std::rc::Rc; -pub fn init(i: &mut CoreIsolate, s: &State) { +pub fn init(i: &mut CoreIsolate, s: &Rc) { i.register_op( "op_apply_source_map", s.stateful_json_op(op_apply_source_map), @@ -29,7 +30,7 @@ struct ApplySourceMap { } fn op_apply_source_map( - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -42,7 +43,7 @@ fn op_apply_source_map( args.line_number.into(), args.column_number.into(), &mut mappings_map, - &state.borrow().global_state.ts_compiler, + &state.global_state.ts_compiler, ); Ok(JsonOp::Sync(json!({ @@ -53,7 +54,7 @@ fn op_apply_source_map( } fn op_format_diagnostic( - _state: &State, + _state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { diff --git a/cli/ops/fetch.rs b/cli/ops/fetch.rs index 5393162601..b320222edc 100644 --- a/cli/ops/fetch.rs +++ b/cli/ops/fetch.rs @@ -14,8 +14,9 @@ use http::Method; use reqwest::Client; use std::convert::From; use std::path::PathBuf; +use std::rc::Rc; -pub fn init(i: &mut CoreIsolate, s: &State) { +pub fn init(i: &mut CoreIsolate, s: &Rc) { i.register_op("op_fetch", s.stateful_json_op2(op_fetch)); i.register_op( "op_create_http_client", @@ -34,22 +35,23 @@ struct FetchArgs { pub fn op_fetch( isolate_state: &mut CoreIsolateState, - state: &State, + state: &Rc, args: Value, data: &mut [ZeroCopyBuf], ) -> Result { let args: FetchArgs = serde_json::from_value(args)?; let url = args.url; let resource_table_ = isolate_state.resource_table.borrow(); - let state_ = state.borrow(); + let mut client_ref_mut; let client = if let Some(rid) = args.client_rid { let r = resource_table_ .get::(rid) .ok_or_else(OpError::bad_resource_id)?; &r.client } else { - &state_.http_client + client_ref_mut = state.http_client.borrow_mut(); + &mut *client_ref_mut }; let method = match args.method { @@ -137,7 +139,7 @@ struct CreateHttpClientOptions { fn op_create_http_client( isolate_state: &mut CoreIsolateState, - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -148,7 +150,7 @@ fn op_create_http_client( state.check_read(&PathBuf::from(ca_file))?; } - let client = create_http_client(args.ca_file).unwrap(); + let client = create_http_client(args.ca_file.as_deref()).unwrap(); let rid = resource_table.add("httpClient", Box::new(HttpClientResource::new(client))); diff --git a/cli/ops/fs.rs b/cli/ops/fs.rs index 2e6f076a6e..0fd6ad5efd 100644 --- a/cli/ops/fs.rs +++ b/cli/ops/fs.rs @@ -23,7 +23,7 @@ use std::time::UNIX_EPOCH; use rand::{thread_rng, Rng}; -pub fn init(i: &mut CoreIsolate, s: &State) { +pub fn init(i: &mut CoreIsolate, s: &Rc) { let t = &CoreIsolate::state(i).borrow().resource_table.clone(); i.register_op("op_open_sync", s.stateful_json_op_sync(t, op_open_sync)); @@ -140,7 +140,7 @@ fn op_open_sync( } async fn op_open_async( - state: State, + state: Rc, resource_table: Rc>, args: Value, _zero_copy: BufVec, @@ -170,7 +170,7 @@ struct SeekArgs { fn op_seek( isolate_state: &mut CoreIsolateState, - _state: &State, + _state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -230,7 +230,7 @@ struct FdatasyncArgs { fn op_fdatasync( isolate_state: &mut CoreIsolateState, - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -274,7 +274,7 @@ struct FsyncArgs { fn op_fsync( isolate_state: &mut CoreIsolateState, - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -318,7 +318,7 @@ struct FstatArgs { fn op_fstat( isolate_state: &mut CoreIsolateState, - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -360,7 +360,7 @@ struct UmaskArgs { } fn op_umask( - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -398,7 +398,7 @@ struct ChdirArgs { } fn op_chdir( - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -419,7 +419,7 @@ struct MkdirArgs { } fn op_mkdir( - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -453,7 +453,7 @@ struct ChmodArgs { } fn op_chmod( - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -493,7 +493,7 @@ struct ChownArgs { } fn op_chown( - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -530,7 +530,7 @@ struct RemoveArgs { } fn op_remove( - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -584,7 +584,7 @@ struct CopyFileArgs { } fn op_copy_file( - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -678,7 +678,7 @@ struct StatArgs { } fn op_stat( - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -708,7 +708,7 @@ struct RealpathArgs { } fn op_realpath( - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -743,7 +743,7 @@ struct ReadDirArgs { } fn op_read_dir( - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -786,7 +786,7 @@ struct RenameArgs { } fn op_rename( - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -815,7 +815,7 @@ struct LinkArgs { } fn op_link( - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -853,7 +853,7 @@ struct SymlinkOptions { } fn op_symlink( - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -913,7 +913,7 @@ struct ReadLinkArgs { } fn op_read_link( - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -941,7 +941,7 @@ struct FtruncateArgs { fn op_ftruncate( isolate_state: &mut CoreIsolateState, - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -986,7 +986,7 @@ struct TruncateArgs { } fn op_truncate( - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -1060,7 +1060,7 @@ struct MakeTempArgs { } fn op_make_temp_dir( - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -1091,7 +1091,7 @@ fn op_make_temp_dir( } fn op_make_temp_file( - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -1131,7 +1131,7 @@ struct UtimeArgs { } fn op_utime( - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -1151,7 +1151,7 @@ fn op_utime( } fn op_cwd( - state: &State, + state: &Rc, _args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { diff --git a/cli/ops/fs_events.rs b/cli/ops/fs_events.rs index b9d54fc3e5..fcaf138f82 100644 --- a/cli/ops/fs_events.rs +++ b/cli/ops/fs_events.rs @@ -17,9 +17,10 @@ use notify::Watcher; use serde::Serialize; use std::convert::From; use std::path::PathBuf; +use std::rc::Rc; use tokio::sync::mpsc; -pub fn init(i: &mut CoreIsolate, s: &State) { +pub fn init(i: &mut CoreIsolate, s: &Rc) { i.register_op("op_fs_events_open", s.stateful_json_op2(op_fs_events_open)); i.register_op("op_fs_events_poll", s.stateful_json_op2(op_fs_events_poll)); } @@ -64,7 +65,7 @@ impl From for FsEvent { pub fn op_fs_events_open( isolate_state: &mut CoreIsolateState, - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -102,7 +103,7 @@ pub fn op_fs_events_open( pub fn op_fs_events_poll( isolate_state: &mut CoreIsolateState, - _state: &State, + _state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { diff --git a/cli/ops/idna.rs b/cli/ops/idna.rs index ee78307dc9..c76ceba89b 100644 --- a/cli/ops/idna.rs +++ b/cli/ops/idna.rs @@ -8,8 +8,9 @@ use crate::state::State; use deno_core::CoreIsolate; use deno_core::ZeroCopyBuf; use idna::{domain_to_ascii, domain_to_ascii_strict}; +use std::rc::Rc; -pub fn init(i: &mut CoreIsolate, s: &State) { +pub fn init(i: &mut CoreIsolate, s: &Rc) { i.register_op("op_domain_to_ascii", s.stateful_json_op(op_domain_to_ascii)); } @@ -21,7 +22,7 @@ struct DomainToAscii { } fn op_domain_to_ascii( - _state: &State, + _state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { diff --git a/cli/ops/io.rs b/cli/ops/io.rs index c35e0d4b67..4d03e0ef71 100644 --- a/cli/ops/io.rs +++ b/cli/ops/io.rs @@ -11,6 +11,7 @@ use futures::future::FutureExt; use futures::ready; use std::collections::HashMap; use std::pin::Pin; +use std::rc::Rc; use std::sync::atomic::{AtomicUsize, Ordering}; use std::task::Context; use std::task::Poll; @@ -84,7 +85,7 @@ lazy_static! { }; } -pub fn init(i: &mut CoreIsolate, s: &State) { +pub fn init(i: &mut CoreIsolate, s: &Rc) { i.register_op("op_read", s.stateful_minimal_op2(op_read)); i.register_op("op_write", s.stateful_minimal_op2(op_write)); } @@ -236,7 +237,7 @@ impl DenoAsyncRead for StreamResource { pub fn op_read( isolate_state: &mut CoreIsolateState, - _state: &State, + _state: &Rc, is_sync: bool, rid: i32, zero_copy: &mut [ZeroCopyBuf], @@ -361,7 +362,7 @@ impl DenoAsyncWrite for StreamResource { pub fn op_write( isolate_state: &mut CoreIsolateState, - _state: &State, + _state: &Rc, is_sync: bool, rid: i32, zero_copy: &mut [ZeroCopyBuf], diff --git a/cli/ops/net.rs b/cli/ops/net.rs index 76abcb6c30..445c691063 100644 --- a/cli/ops/net.rs +++ b/cli/ops/net.rs @@ -13,6 +13,7 @@ use futures::future::FutureExt; use std::convert::From; use std::net::Shutdown; use std::net::SocketAddr; +use std::rc::Rc; use std::task::Context; use std::task::Poll; use tokio::net::TcpListener; @@ -22,7 +23,7 @@ use tokio::net::UdpSocket; #[cfg(unix)] use super::net_unix; -pub fn init(i: &mut CoreIsolate, s: &State) { +pub fn init(i: &mut CoreIsolate, s: &Rc) { i.register_op("op_accept", s.stateful_json_op2(op_accept)); i.register_op("op_connect", s.stateful_json_op2(op_connect)); i.register_op("op_shutdown", s.stateful_json_op2(op_shutdown)); @@ -102,7 +103,7 @@ fn accept_tcp( fn op_accept( isolate_state: &mut CoreIsolateState, - _state: &State, + _state: &Rc, args: Value, zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -126,7 +127,7 @@ struct ReceiveArgs { fn receive_udp( isolate_state: &mut CoreIsolateState, - _state: &State, + _state: &Rc, args: ReceiveArgs, zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -166,7 +167,7 @@ fn receive_udp( fn op_datagram_receive( isolate_state: &mut CoreIsolateState, - state: &State, + state: &Rc, args: Value, zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -196,7 +197,7 @@ struct SendArgs { fn op_datagram_send( isolate_state: &mut CoreIsolateState, - state: &State, + state: &Rc, args: Value, zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -266,7 +267,7 @@ struct ConnectArgs { fn op_connect( isolate_state: &mut CoreIsolateState, - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -352,7 +353,7 @@ struct ShutdownArgs { fn op_shutdown( isolate_state: &mut CoreIsolateState, - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -494,7 +495,7 @@ fn listen_udp( fn op_listen( isolate_state: &mut CoreIsolateState, - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { diff --git a/cli/ops/os.rs b/cli/ops/os.rs index f084f213bf..e46aff3e61 100644 --- a/cli/ops/os.rs +++ b/cli/ops/os.rs @@ -6,9 +6,10 @@ use deno_core::CoreIsolate; use deno_core::ZeroCopyBuf; use std::collections::HashMap; use std::env; +use std::rc::Rc; use url::Url; -pub fn init(i: &mut CoreIsolate, s: &State) { +pub fn init(i: &mut CoreIsolate, s: &Rc) { i.register_op("op_exit", s.stateful_json_op(op_exit)); i.register_op("op_env", s.stateful_json_op(op_env)); i.register_op("op_exec_path", s.stateful_json_op(op_exec_path)); @@ -21,7 +22,7 @@ pub fn init(i: &mut CoreIsolate, s: &State) { } fn op_exec_path( - state: &State, + state: &Rc, _args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -41,7 +42,7 @@ struct SetEnv { } fn op_set_env( - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -52,7 +53,7 @@ fn op_set_env( } fn op_env( - state: &State, + state: &Rc, _args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -67,7 +68,7 @@ struct GetEnv { } fn op_get_env( - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -86,7 +87,7 @@ struct DeleteEnv { } fn op_delete_env( - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -102,7 +103,7 @@ struct Exit { } fn op_exit( - _s: &State, + _s: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -111,7 +112,7 @@ fn op_exit( } fn op_loadavg( - state: &State, + state: &Rc, _args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -128,7 +129,7 @@ fn op_loadavg( } fn op_hostname( - state: &State, + state: &Rc, _args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -139,7 +140,7 @@ fn op_hostname( } fn op_os_release( - state: &State, + state: &Rc, _args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { diff --git a/cli/ops/permissions.rs b/cli/ops/permissions.rs index 571ea5b21c..4cb9985367 100644 --- a/cli/ops/permissions.rs +++ b/cli/ops/permissions.rs @@ -5,8 +5,9 @@ use crate::state::State; use deno_core::CoreIsolate; use deno_core::ZeroCopyBuf; use std::path::Path; +use std::rc::Rc; -pub fn init(i: &mut CoreIsolate, s: &State) { +pub fn init(i: &mut CoreIsolate, s: &Rc) { i.register_op( "op_query_permission", s.stateful_json_op(op_query_permission), @@ -29,13 +30,12 @@ struct PermissionArgs { } pub fn op_query_permission( - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { let args: PermissionArgs = serde_json::from_value(args)?; - let state = state.borrow(); - let permissions = &state.permissions; + let permissions = state.permissions.borrow(); let path = args.path.as_deref(); let perm = match args.name.as_ref() { "read" => permissions.query_read(&path.as_deref().map(Path::new)), @@ -51,13 +51,12 @@ pub fn op_query_permission( } pub fn op_revoke_permission( - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { let args: PermissionArgs = serde_json::from_value(args)?; - let mut state = state.borrow_mut(); - let permissions = &mut state.permissions; + let mut permissions = state.permissions.borrow_mut(); let path = args.path.as_deref(); let perm = match args.name.as_ref() { "read" => permissions.revoke_read(&path.as_deref().map(Path::new)), @@ -73,13 +72,12 @@ pub fn op_revoke_permission( } pub fn op_request_permission( - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { let args: PermissionArgs = serde_json::from_value(args)?; - let mut state = state.borrow_mut(); - let permissions = &mut state.permissions; + let permissions = &mut state.permissions.borrow_mut(); let path = args.path.as_deref(); let perm = match args.name.as_ref() { "read" => permissions.request_read(&path.as_deref().map(Path::new)), diff --git a/cli/ops/plugin.rs b/cli/ops/plugin.rs index 16debac50a..3fb1494043 100644 --- a/cli/ops/plugin.rs +++ b/cli/ops/plugin.rs @@ -20,7 +20,7 @@ use std::rc::Rc; use std::task::Context; use std::task::Poll; -pub fn init(i: &mut CoreIsolate, s: &State) { +pub fn init(i: &mut CoreIsolate, s: &Rc) { i.register_op( "op_open_plugin", s.core_op(json_op(s.stateful_op2(op_open_plugin))), @@ -35,7 +35,7 @@ struct OpenPluginArgs { pub fn op_open_plugin( isolate_state: &mut CoreIsolateState, - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { diff --git a/cli/ops/process.rs b/cli/ops/process.rs index 384068e6af..bf733a78e9 100644 --- a/cli/ops/process.rs +++ b/cli/ops/process.rs @@ -12,12 +12,13 @@ use futures::future::poll_fn; use futures::future::FutureExt; use futures::TryFutureExt; use std::convert::From; +use std::rc::Rc; use tokio::process::Command; #[cfg(unix)] use std::os::unix::process::ExitStatusExt; -pub fn init(i: &mut CoreIsolate, s: &State) { +pub fn init(i: &mut CoreIsolate, s: &Rc) { i.register_op("op_run", s.stateful_json_op2(op_run)); i.register_op("op_run_status", s.stateful_json_op2(op_run_status)); i.register_op("op_kill", s.stateful_json_op(op_kill)); @@ -62,7 +63,7 @@ struct ChildResource { fn op_run( isolate_state: &mut CoreIsolateState, - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -173,7 +174,7 @@ struct RunStatusArgs { fn op_run_status( isolate_state: &mut CoreIsolateState, - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -223,7 +224,7 @@ struct KillArgs { } fn op_kill( - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { diff --git a/cli/ops/random.rs b/cli/ops/random.rs index b29c761b86..275f264f9f 100644 --- a/cli/ops/random.rs +++ b/cli/ops/random.rs @@ -6,8 +6,9 @@ use deno_core::CoreIsolate; use deno_core::ZeroCopyBuf; use rand::thread_rng; use rand::Rng; +use std::rc::Rc; -pub fn init(i: &mut CoreIsolate, s: &State) { +pub fn init(i: &mut CoreIsolate, s: &Rc) { i.register_op( "op_get_random_values", s.stateful_json_op(op_get_random_values), @@ -15,14 +16,14 @@ pub fn init(i: &mut CoreIsolate, s: &State) { } fn op_get_random_values( - state: &State, + state: &Rc, _args: Value, zero_copy: &mut [ZeroCopyBuf], ) -> Result { assert_eq!(zero_copy.len(), 1); - if let Some(ref mut seeded_rng) = state.borrow_mut().seeded_rng { - seeded_rng.fill(&mut *zero_copy[0]); + if let Some(seeded_rng) = &state.seeded_rng { + seeded_rng.borrow_mut().fill(&mut *zero_copy[0]); } else { let mut rng = thread_rng(); rng.fill(&mut *zero_copy[0]); diff --git a/cli/ops/repl.rs b/cli/ops/repl.rs index b8fd7ab8b3..88b7de8819 100644 --- a/cli/ops/repl.rs +++ b/cli/ops/repl.rs @@ -7,10 +7,11 @@ use crate::state::State; use deno_core::CoreIsolate; use deno_core::CoreIsolateState; use deno_core::ZeroCopyBuf; +use std::rc::Rc; use std::sync::Arc; use std::sync::Mutex; -pub fn init(i: &mut CoreIsolate, s: &State) { +pub fn init(i: &mut CoreIsolate, s: &Rc) { i.register_op("op_repl_start", s.stateful_json_op2(op_repl_start)); i.register_op("op_repl_readline", s.stateful_json_op2(op_repl_readline)); } @@ -25,14 +26,14 @@ struct ReplStartArgs { fn op_repl_start( isolate_state: &mut CoreIsolateState, - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { let args: ReplStartArgs = serde_json::from_value(args)?; debug!("op_repl_start {}", args.history_file); let history_path = - repl::history_path(&state.borrow().global_state.dir, &args.history_file); + repl::history_path(&state.global_state.dir, &args.history_file); let repl = repl::Repl::new(history_path); let resource = ReplResource(Arc::new(Mutex::new(repl))); let mut resource_table = isolate_state.resource_table.borrow_mut(); @@ -48,7 +49,7 @@ struct ReplReadlineArgs { fn op_repl_readline( isolate_state: &mut CoreIsolateState, - _state: &State, + _state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { diff --git a/cli/ops/resources.rs b/cli/ops/resources.rs index a66a661700..a24b3b3823 100644 --- a/cli/ops/resources.rs +++ b/cli/ops/resources.rs @@ -5,15 +5,16 @@ use crate::state::State; use deno_core::CoreIsolate; use deno_core::CoreIsolateState; use deno_core::ZeroCopyBuf; +use std::rc::Rc; -pub fn init(i: &mut CoreIsolate, s: &State) { +pub fn init(i: &mut CoreIsolate, s: &Rc) { i.register_op("op_resources", s.stateful_json_op2(op_resources)); i.register_op("op_close", s.stateful_json_op2(op_close)); } fn op_resources( isolate_state: &mut CoreIsolateState, - _state: &State, + _state: &Rc, _args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -24,7 +25,7 @@ fn op_resources( /// op_close removes a resource from the resource table. fn op_close( isolate_state: &mut CoreIsolateState, - _state: &State, + _state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { diff --git a/cli/ops/runtime.rs b/cli/ops/runtime.rs index 55f0d9f576..b4fb3c496d 100644 --- a/cli/ops/runtime.rs +++ b/cli/ops/runtime.rs @@ -9,19 +9,19 @@ use deno_core::CoreIsolate; use deno_core::ModuleSpecifier; use deno_core::ZeroCopyBuf; use std::env; +use std::rc::Rc; -pub fn init(i: &mut CoreIsolate, s: &State) { +pub fn init(i: &mut CoreIsolate, s: &Rc) { i.register_op("op_start", s.stateful_json_op(op_start)); i.register_op("op_main_module", s.stateful_json_op(op_main_module)); i.register_op("op_metrics", s.stateful_json_op(op_metrics)); } fn op_start( - state: &State, + state: &Rc, _args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { - let state = state.borrow(); let gs = &state.global_state; Ok(JsonOp::Sync(json!({ @@ -43,11 +43,11 @@ fn op_start( } fn op_main_module( - state: &State, + state: &Rc, _args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { - let main = &state.borrow().main_module.to_string(); + let main = &state.main_module.to_string(); let main_url = ModuleSpecifier::resolve_url_or_path(&main)?; if main_url.as_url().scheme() == "file" { let main_path = std::env::current_dir().unwrap().join(main_url.to_string()); @@ -57,12 +57,11 @@ fn op_main_module( } fn op_metrics( - state: &State, + state: &Rc, _args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { - let state = state.borrow(); - let m = &state.metrics; + let m = &state.metrics.borrow(); Ok(JsonOp::Sync(json!({ "opsDispatched": m.ops_dispatched, diff --git a/cli/ops/runtime_compiler.rs b/cli/ops/runtime_compiler.rs index e70b69de73..d77ab8f08e 100644 --- a/cli/ops/runtime_compiler.rs +++ b/cli/ops/runtime_compiler.rs @@ -9,8 +9,9 @@ use crate::tsc::runtime_transpile; use deno_core::CoreIsolate; use deno_core::ZeroCopyBuf; use std::collections::HashMap; +use std::rc::Rc; -pub fn init(i: &mut CoreIsolate, s: &State) { +pub fn init(i: &mut CoreIsolate, s: &Rc) { i.register_op("op_compile", s.stateful_json_op(op_compile)); i.register_op("op_transpile", s.stateful_json_op(op_transpile)); } @@ -25,19 +26,18 @@ struct CompileArgs { } fn op_compile( - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { state.check_unstable("Deno.compile"); let args: CompileArgs = serde_json::from_value(args)?; - let s = state.borrow(); - let global_state = s.global_state.clone(); - let permissions = s.permissions.clone(); + let global_state = state.global_state.clone(); + let permissions = state.permissions.borrow().clone(); let fut = async move { let fut = if args.bundle { runtime_bundle( - global_state, + &global_state, permissions, &args.root_name, &args.sources, @@ -46,7 +46,7 @@ fn op_compile( .boxed_local() } else { runtime_compile( - global_state, + &global_state, permissions, &args.root_name, &args.sources, @@ -68,17 +68,16 @@ struct TranspileArgs { } fn op_transpile( - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { state.check_unstable("Deno.transpile"); let args: TranspileArgs = serde_json::from_value(args)?; - let s = state.borrow(); - let global_state = s.global_state.clone(); - let permissions = s.permissions.clone(); + let global_state = state.global_state.clone(); + let permissions = state.permissions.borrow().clone(); let fut = async move { - runtime_transpile(global_state, permissions, &args.sources, &args.options) + runtime_transpile(&global_state, permissions, &args.sources, &args.options) .await } .boxed_local(); diff --git a/cli/ops/signal.rs b/cli/ops/signal.rs index 6457ac42e4..cb83427c89 100644 --- a/cli/ops/signal.rs +++ b/cli/ops/signal.rs @@ -5,6 +5,7 @@ use crate::state::State; use deno_core::CoreIsolate; use deno_core::CoreIsolateState; use deno_core::ZeroCopyBuf; +use std::rc::Rc; #[cfg(unix)] use super::dispatch_json::Deserialize; @@ -15,7 +16,7 @@ use std::task::Waker; #[cfg(unix)] use tokio::signal::unix::{signal, Signal, SignalKind}; -pub fn init(i: &mut CoreIsolate, s: &State) { +pub fn init(i: &mut CoreIsolate, s: &Rc) { i.register_op("op_signal_bind", s.stateful_json_op2(op_signal_bind)); i.register_op("op_signal_unbind", s.stateful_json_op2(op_signal_unbind)); i.register_op("op_signal_poll", s.stateful_json_op2(op_signal_poll)); @@ -41,7 +42,7 @@ struct SignalArgs { #[cfg(unix)] fn op_signal_bind( isolate_state: &mut CoreIsolateState, - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -63,7 +64,7 @@ fn op_signal_bind( #[cfg(unix)] fn op_signal_poll( isolate_state: &mut CoreIsolateState, - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -90,7 +91,7 @@ fn op_signal_poll( #[cfg(unix)] pub fn op_signal_unbind( isolate_state: &mut CoreIsolateState, - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -115,7 +116,7 @@ pub fn op_signal_unbind( #[cfg(not(unix))] pub fn op_signal_bind( _isolate_state: &mut CoreIsolateState, - _state: &State, + _state: &Rc, _args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -125,7 +126,7 @@ pub fn op_signal_bind( #[cfg(not(unix))] fn op_signal_unbind( _isolate_state: &mut CoreIsolateState, - _state: &State, + _state: &Rc, _args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -135,7 +136,7 @@ fn op_signal_unbind( #[cfg(not(unix))] fn op_signal_poll( _isolate_state: &mut CoreIsolateState, - _state: &State, + _state: &Rc, _args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { diff --git a/cli/ops/timers.rs b/cli/ops/timers.rs index 21efa8cf9f..e3fe14c2c7 100644 --- a/cli/ops/timers.rs +++ b/cli/ops/timers.rs @@ -5,10 +5,11 @@ use crate::state::State; use deno_core::CoreIsolate; use deno_core::ZeroCopyBuf; use futures::future::FutureExt; +use std::rc::Rc; use std::time::Duration; use std::time::Instant; -pub fn init(i: &mut CoreIsolate, s: &State) { +pub fn init(i: &mut CoreIsolate, s: &Rc) { i.register_op( "op_global_timer_stop", s.stateful_json_op(op_global_timer_stop), @@ -18,12 +19,11 @@ pub fn init(i: &mut CoreIsolate, s: &State) { } fn op_global_timer_stop( - state: &State, + state: &Rc, _args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { - let mut state = state.borrow_mut(); - state.global_timer.cancel(); + state.global_timer.borrow_mut().cancel(); Ok(JsonOp::Sync(json!({}))) } @@ -33,17 +33,17 @@ struct GlobalTimerArgs { } fn op_global_timer( - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { let args: GlobalTimerArgs = serde_json::from_value(args)?; let val = args.timeout; - let mut state = state.borrow_mut(); let deadline = Instant::now() + Duration::from_millis(val); let f = state .global_timer + .borrow_mut() .new_timeout(deadline) .then(move |_| futures::future::ok(json!({}))); @@ -55,13 +55,12 @@ fn op_global_timer( // If the High precision flag is not set, the // nanoseconds are rounded on 2ms. fn op_now( - state: &State, + state: &Rc, _args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { - let inner_state = state.borrow(); - let seconds = inner_state.start_time.elapsed().as_secs(); - let mut subsec_nanos = inner_state.start_time.elapsed().subsec_nanos(); + let seconds = state.start_time.elapsed().as_secs(); + let mut subsec_nanos = state.start_time.elapsed().subsec_nanos(); let reduced_time_precision = 2_000_000; // 2ms in nanoseconds // If the permission is not enabled diff --git a/cli/ops/tls.rs b/cli/ops/tls.rs index 3e22c71ea6..76962f5c8f 100644 --- a/cli/ops/tls.rs +++ b/cli/ops/tls.rs @@ -14,6 +14,7 @@ use std::fs::File; use std::io::BufReader; use std::net::SocketAddr; use std::path::Path; +use std::rc::Rc; use std::sync::Arc; use std::task::Context; use std::task::Poll; @@ -29,7 +30,7 @@ use tokio_rustls::{ }; use webpki::DNSNameRef; -pub fn init(i: &mut CoreIsolate, s: &State) { +pub fn init(i: &mut CoreIsolate, s: &Rc) { i.register_op("op_start_tls", s.stateful_json_op2(op_start_tls)); i.register_op("op_connect_tls", s.stateful_json_op2(op_connect_tls)); i.register_op("op_listen_tls", s.stateful_json_op2(op_listen_tls)); @@ -55,7 +56,7 @@ struct StartTLSArgs { pub fn op_start_tls( isolate_state: &mut CoreIsolateState, - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -134,7 +135,7 @@ pub fn op_start_tls( pub fn op_connect_tls( isolate_state: &mut CoreIsolateState, - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -308,7 +309,7 @@ struct ListenTlsArgs { fn op_listen_tls( isolate_state: &mut CoreIsolateState, - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -358,7 +359,7 @@ struct AcceptTlsArgs { fn op_accept_tls( isolate_state: &mut CoreIsolateState, - _state: &State, + _state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { diff --git a/cli/ops/tty.rs b/cli/ops/tty.rs index d86100232f..d6aaeb7854 100644 --- a/cli/ops/tty.rs +++ b/cli/ops/tty.rs @@ -10,6 +10,7 @@ use deno_core::ZeroCopyBuf; use nix::sys::termios; use serde_derive::{Deserialize, Serialize}; use serde_json::Value; +use std::rc::Rc; #[cfg(windows)] use winapi::shared::minwindef::DWORD; @@ -35,7 +36,7 @@ fn get_windows_handle( Ok(handle) } -pub fn init(i: &mut CoreIsolate, s: &State) { +pub fn init(i: &mut CoreIsolate, s: &Rc) { i.register_op("op_set_raw", s.stateful_json_op2(op_set_raw)); i.register_op("op_isatty", s.stateful_json_op2(op_isatty)); i.register_op("op_console_size", s.stateful_json_op2(op_console_size)); @@ -49,7 +50,7 @@ struct SetRawArgs { pub fn op_set_raw( isolate_state: &mut CoreIsolateState, - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -218,7 +219,7 @@ struct IsattyArgs { pub fn op_isatty( isolate_state: &mut CoreIsolateState, - _state: &State, + _state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { @@ -265,7 +266,7 @@ struct ConsoleSize { pub fn op_console_size( isolate_state: &mut CoreIsolateState, - state: &State, + state: &Rc, args: Value, _zero_copy: &mut [ZeroCopyBuf], ) -> Result { diff --git a/cli/ops/web_worker.rs b/cli/ops/web_worker.rs index 553278b074..8ad497d5cd 100644 --- a/cli/ops/web_worker.rs +++ b/cli/ops/web_worker.rs @@ -10,6 +10,7 @@ use deno_core::CoreIsolateState; use deno_core::ZeroCopyBuf; use futures::channel::mpsc; use std::convert::From; +use std::rc::Rc; pub fn web_worker_op( sender: mpsc::Sender, @@ -59,7 +60,7 @@ where pub fn init( i: &mut CoreIsolate, - s: &State, + s: &Rc, sender: &mpsc::Sender, handle: WebWorkerHandle, ) { diff --git a/cli/ops/worker_host.rs b/cli/ops/worker_host.rs index e3571f7133..47ebd9c7f7 100644 --- a/cli/ops/worker_host.rs +++ b/cli/ops/worker_host.rs @@ -17,9 +17,11 @@ use deno_core::ModuleSpecifier; use deno_core::ZeroCopyBuf; use futures::future::FutureExt; use std::convert::From; +use std::rc::Rc; +use std::sync::Arc; use std::thread::JoinHandle; -pub fn init(i: &mut CoreIsolate, s: &State) { +pub fn init(i: &mut CoreIsolate, s: &Rc) { i.register_op("op_create_worker", s.stateful_json_op(op_create_worker)); i.register_op( "op_host_terminate_worker", @@ -38,7 +40,7 @@ pub fn init(i: &mut CoreIsolate, s: &State) { fn create_web_worker( worker_id: u32, name: String, - global_state: GlobalState, + global_state: &Arc, permissions: Permissions, specifier: ModuleSpecifier, has_deno_namespace: bool, @@ -49,7 +51,7 @@ fn create_web_worker( let mut worker = WebWorker::new( name.clone(), startup_data::deno_isolate_init(), - state, + &state, has_deno_namespace, ); @@ -84,12 +86,13 @@ fn create_web_worker( fn run_worker_thread( worker_id: u32, name: String, - global_state: GlobalState, + global_state: &Arc, permissions: Permissions, specifier: ModuleSpecifier, has_deno_namespace: bool, maybe_source_code: Option, ) -> Result<(JoinHandle<()>, WebWorkerHandle), ErrBox> { + let global_state = global_state.clone(); let (handle_sender, handle_receiver) = std::sync::mpsc::sync_channel::>(1); @@ -103,7 +106,7 @@ fn run_worker_thread( let result = create_web_worker( worker_id, name, - global_state, + &global_state, permissions, specifier.clone(), has_deno_namespace, @@ -178,7 +181,7 @@ struct CreateWorkerArgs { /// Create worker as the host fn op_create_worker( - state: &State, + state: &Rc, args: Value, _data: &mut [ZeroCopyBuf], ) -> Result { @@ -196,12 +199,10 @@ fn op_create_worker( state.check_unstable("Worker.deno"); } let parent_state = state.clone(); - let mut state = state.borrow_mut(); let global_state = state.global_state.clone(); - let permissions = state.permissions.clone(); - let worker_id = state.next_worker_id; - state.next_worker_id += 1; - drop(state); + let permissions = state.permissions.borrow().clone(); + let worker_id = state.next_worker_id.get(); + state.next_worker_id.set(worker_id + 1); let module_specifier = ModuleSpecifier::resolve_url(&specifier)?; let worker_name = args_name.unwrap_or_else(|| "".to_string()); @@ -209,7 +210,7 @@ fn op_create_worker( let (join_handle, worker_handle) = run_worker_thread( worker_id, worker_name, - global_state, + &global_state, permissions, module_specifier, use_deno_namespace, @@ -218,9 +219,9 @@ fn op_create_worker( .map_err(|e| OpError::other(e.to_string()))?; // At this point all interactions with worker happen using thread // safe handler returned from previous function call - let mut parent_state = parent_state.borrow_mut(); parent_state .workers + .borrow_mut() .insert(worker_id, (join_handle, worker_handle)); Ok(JsonOp::Sync(json!({ "id": worker_id }))) @@ -232,15 +233,17 @@ struct WorkerArgs { } fn op_host_terminate_worker( - state: &State, + state: &Rc, args: Value, _data: &mut [ZeroCopyBuf], ) -> Result { let args: WorkerArgs = serde_json::from_value(args)?; let id = args.id as u32; - let mut state = state.borrow_mut(); - let (join_handle, worker_handle) = - state.workers.remove(&id).expect("No worker handle found"); + let (join_handle, worker_handle) = state + .workers + .borrow_mut() + .remove(&id) + .expect("No worker handle found"); worker_handle.terminate(); join_handle.join().expect("Panic in worker thread"); Ok(JsonOp::Sync(json!({}))) @@ -298,27 +301,21 @@ fn serialize_worker_event(event: WorkerEvent) -> Value { /// Get message from guest worker as host fn op_host_get_message( - state: &State, + state: &Rc, args: Value, _data: &mut [ZeroCopyBuf], ) -> Result { let args: WorkerArgs = serde_json::from_value(args)?; let id = args.id as u32; - let worker_handle = { - let state_ = state.borrow(); - let (_join_handle, worker_handle) = - state_.workers.get(&id).expect("No worker handle found"); - worker_handle.clone() - }; - let state_ = state.clone(); + let state = state.clone(); + let worker_handle = state.workers.borrow()[&id].1.clone(); let op = async move { let response = match worker_handle.get_event().await? { Some(event) => { // Terminal error means that worker should be removed from worker table. if let WorkerEvent::TerminalError(_) = &event { - let mut state_ = state_.borrow_mut(); if let Some((join_handle, mut worker_handle)) = - state_.workers.remove(&id) + state.workers.borrow_mut().remove(&id) { worker_handle.sender.close_channel(); join_handle.join().expect("Worker thread panicked"); @@ -328,12 +325,10 @@ fn op_host_get_message( } None => { // Worker shuts down - let mut state_ = state_.borrow_mut(); + let mut workers = state.workers.borrow_mut(); // Try to remove worker from workers table - NOTE: `Worker.terminate()` might have been called // already meaning that we won't find worker in table - in that case ignore. - if let Some((join_handle, mut worker_handle)) = - state_.workers.remove(&id) - { + if let Some((join_handle, mut worker_handle)) = workers.remove(&id) { worker_handle.sender.close_channel(); join_handle.join().expect("Worker thread panicked"); } @@ -347,7 +342,7 @@ fn op_host_get_message( /// Post message to guest worker as host fn op_host_post_message( - state: &State, + state: &Rc, args: Value, data: &mut [ZeroCopyBuf], ) -> Result { @@ -357,9 +352,8 @@ fn op_host_post_message( let msg = Vec::from(&*data[0]).into_boxed_slice(); debug!("post message to worker {}", id); - let state = state.borrow(); - let (_, worker_handle) = - state.workers.get(&id).expect("No worker handle found"); + let workers = state.workers.borrow(); + let worker_handle = workers[&id].1.clone(); worker_handle .post_message(msg) .map_err(|e| OpError::other(e.to_string()))?; diff --git a/cli/state.rs b/cli/state.rs index 5754e8c9d5..055c09916e 100644 --- a/cli/state.rs +++ b/cli/state.rs @@ -27,60 +27,51 @@ use futures::Future; use rand::rngs::StdRng; use rand::SeedableRng; use serde_json::Value; +use std::cell::Cell; use std::cell::RefCell; use std::collections::HashMap; -use std::ops::Deref; use std::path::Path; use std::pin::Pin; use std::rc::Rc; use std::str; +use std::sync::Arc; use std::thread::JoinHandle; use std::time::Instant; -#[derive(Clone)] -pub struct State(Rc>); - -impl Deref for State { - type Target = Rc>; - fn deref(&self) -> &Self::Target { - &self.0 - } -} - #[cfg_attr(feature = "cargo-clippy", allow(stutter))] -pub struct StateInner { - pub global_state: GlobalState, - pub permissions: Permissions, +pub struct State { + pub global_state: Arc, + pub permissions: RefCell, pub main_module: ModuleSpecifier, /// When flags contains a `.import_map_path` option, the content of the /// import map file will be resolved and set. pub import_map: Option, - pub metrics: Metrics, - pub global_timer: GlobalTimer, - pub workers: HashMap, WebWorkerHandle)>, - pub next_worker_id: u32, + pub metrics: RefCell, + pub global_timer: RefCell, + pub workers: RefCell, WebWorkerHandle)>>, + pub next_worker_id: Cell, pub start_time: Instant, - pub seeded_rng: Option, + pub seeded_rng: Option>, pub target_lib: TargetLib, pub is_main: bool, pub is_internal: bool, - pub http_client: reqwest::Client, + pub http_client: RefCell, } impl State { pub fn stateful_json_op( - &self, + self: &Rc, dispatcher: D, ) -> impl Fn(&mut deno_core::CoreIsolateState, &mut [ZeroCopyBuf]) -> Op where - D: Fn(&State, Value, &mut [ZeroCopyBuf]) -> Result, + D: Fn(&Rc, Value, &mut [ZeroCopyBuf]) -> Result, { use crate::ops::json_op; self.core_op(json_op(self.stateful_op(dispatcher))) } pub fn stateful_json_op_sync( - &self, + self: &Rc, resource_table: &Rc>, dispatcher: D, ) -> impl Fn(&mut deno_core::CoreIsolateState, &mut [ZeroCopyBuf]) -> Op @@ -117,12 +108,13 @@ impl State { } pub fn stateful_json_op_async( - &self, + self: &Rc, resource_table: &Rc>, dispatcher: D, ) -> impl Fn(&mut CoreIsolateState, &mut [ZeroCopyBuf]) -> Op where - D: FnOnce(State, Rc>, Value, BufVec) -> F + Clone, + D: + FnOnce(Rc, Rc>, Value, BufVec) -> F + Clone, F: Future> + 'static, { let state = self.clone(); @@ -167,13 +159,13 @@ impl State { } pub fn stateful_json_op2( - &self, + self: &Rc, dispatcher: D, ) -> impl Fn(&mut deno_core::CoreIsolateState, &mut [ZeroCopyBuf]) -> Op where D: Fn( &mut deno_core::CoreIsolateState, - &State, + &Rc, Value, &mut [ZeroCopyBuf], ) -> Result, @@ -186,7 +178,7 @@ impl State { // TODO(ry) this should be private. Is called by stateful_json_op or // stateful_minimal_op pub fn core_op( - &self, + self: &Rc, dispatcher: D, ) -> impl Fn(&mut deno_core::CoreIsolateState, &mut [ZeroCopyBuf]) -> Op where @@ -206,8 +198,7 @@ impl State { match op { Op::Sync(buf) => { - let mut state_ = state.borrow_mut(); - state_.metrics.op_sync( + state.metrics.borrow_mut().op_sync( bytes_sent_control, bytes_sent_zero_copy, buf.len() as u64, @@ -215,28 +206,31 @@ impl State { Op::Sync(buf) } Op::Async(fut) => { - let mut state_ = state.borrow_mut(); - state_ + state .metrics + .borrow_mut() .op_dispatched_async(bytes_sent_control, bytes_sent_zero_copy); let state = state.clone(); let result_fut = fut.map(move |buf: Buf| { - let mut state_ = state.borrow_mut(); - state_.metrics.op_completed_async(buf.len() as u64); + state + .metrics + .borrow_mut() + .op_completed_async(buf.len() as u64); buf }); Op::Async(result_fut.boxed_local()) } Op::AsyncUnref(fut) => { - let mut state_ = state.borrow_mut(); - state_.metrics.op_dispatched_async_unref( + state.metrics.borrow_mut().op_dispatched_async_unref( bytes_sent_control, bytes_sent_zero_copy, ); let state = state.clone(); let result_fut = fut.map(move |buf: Buf| { - let mut state_ = state.borrow_mut(); - state_.metrics.op_completed_async_unref(buf.len() as u64); + state + .metrics + .borrow_mut() + .op_completed_async_unref(buf.len() as u64); buf }); Op::AsyncUnref(result_fut.boxed_local()) @@ -246,13 +240,13 @@ impl State { } pub fn stateful_minimal_op2( - &self, + self: &Rc, dispatcher: D, ) -> impl Fn(&mut deno_core::CoreIsolateState, &mut [ZeroCopyBuf]) -> Op where D: Fn( &mut deno_core::CoreIsolateState, - &State, + &Rc, bool, i32, &mut [ZeroCopyBuf], @@ -276,7 +270,7 @@ impl State { /// This is a band-aid for transition to `CoreIsolate.register_op` API as most of our /// ops require `state` argument. pub fn stateful_op( - &self, + self: &Rc, dispatcher: D, ) -> impl Fn( &mut deno_core::CoreIsolateState, @@ -284,7 +278,7 @@ impl State { &mut [ZeroCopyBuf], ) -> Result where - D: Fn(&State, Value, &mut [ZeroCopyBuf]) -> Result, + D: Fn(&Rc, Value, &mut [ZeroCopyBuf]) -> Result, { let state = self.clone(); move |_isolate_state: &mut deno_core::CoreIsolateState, @@ -294,7 +288,7 @@ impl State { } pub fn stateful_op2( - &self, + self: &Rc, dispatcher: D, ) -> impl Fn( &mut deno_core::CoreIsolateState, @@ -304,7 +298,7 @@ impl State { where D: Fn( &mut deno_core::CoreIsolateState, - &State, + &Rc, Value, &mut [ZeroCopyBuf], ) -> Result, @@ -322,11 +316,10 @@ impl State { /// /// This is intentionally a non-recoverable check so that people cannot probe /// for unstable APIs from stable programs. - pub fn check_unstable(&self, api_name: &str) { + pub fn check_unstable(self: &Rc, api_name: &str) { // TODO(ry) Maybe use IsolateHandle::terminate_execution here to provide a // stack trace in JS. - let s = self.0.borrow(); - if !s.global_state.flags.unstable { + if !self.global_state.flags.unstable { exit_unstable(api_name); } } @@ -348,7 +341,7 @@ impl ModuleLoader for State { is_main: bool, ) -> Result { if !is_main { - if let Some(import_map) = &self.borrow().import_map { + if let Some(import_map) = &self.import_map { let result = import_map.resolve(specifier, referrer)?; if let Some(r) = result { return Ok(r); @@ -368,11 +361,10 @@ impl ModuleLoader for State { _is_dyn_import: bool, ) -> Pin> { let module_specifier = module_specifier.to_owned(); - let mut state = self.borrow_mut(); // TODO(bartlomieju): incrementing resolve_count here has no sense... - state.metrics.resolve_count += 1; + self.metrics.borrow_mut().resolve_count += 1; let module_url_specified = module_specifier.to_string(); - let global_state = state.global_state.clone(); + let global_state = self.global_state.clone(); // TODO(bartlomieju): `fetch_compiled_module` should take `load_id` param let fut = async move { @@ -399,18 +391,17 @@ impl ModuleLoader for State { is_dyn_import: bool, ) -> Pin>>> { let module_specifier = module_specifier.clone(); - let state = self.borrow(); - let target_lib = state.target_lib.clone(); - let maybe_import_map = state.import_map.clone(); + let target_lib = self.target_lib.clone(); + let maybe_import_map = self.import_map.clone(); // Only "main" module is loaded without permission check, // ie. module that is associated with "is_main" state // and is not a dynamic import. - let permissions = if state.is_main && !is_dyn_import { + let permissions = if self.is_main && !is_dyn_import { Permissions::allow_all() } else { - state.permissions.clone() + self.permissions.borrow().clone() }; - let global_state = state.global_state.clone(); + let global_state = self.global_state.clone(); // TODO(bartlomieju): I'm not sure if it's correct to ignore // bad referrer - this is the case for `Deno.core.evalContext()` where // `ref_str` is ``. @@ -419,7 +410,6 @@ impl ModuleLoader for State { } else { None }; - drop(state); // TODO(bartlomieju): `prepare_module_load` should take `load_id` param async move { @@ -441,87 +431,65 @@ impl ModuleLoader for State { impl State { /// If `shared_permission` is None then permissions from globa state are used. pub fn new( - global_state: GlobalState, + global_state: &Arc, shared_permissions: Option, main_module: ModuleSpecifier, maybe_import_map: Option, is_internal: bool, - ) -> Result { - let seeded_rng = match global_state.flags.seed { - Some(seed) => Some(StdRng::seed_from_u64(seed)), - None => None, - }; - - let permissions = if let Some(perm) = shared_permissions { - perm - } else { - global_state.permissions.clone() - }; - - let http_client = create_http_client(global_state.flags.ca_file.clone())?; - - let state = Rc::new(RefCell::new(StateInner { - global_state, + ) -> Result, ErrBox> { + let fl = &global_state.flags; + let state = State { + global_state: global_state.clone(), main_module, - permissions, + permissions: shared_permissions + .unwrap_or_else(|| global_state.permissions.clone()) + .into(), import_map: maybe_import_map, - metrics: Metrics::default(), - global_timer: GlobalTimer::new(), - workers: HashMap::new(), - next_worker_id: 0, + metrics: Default::default(), + global_timer: Default::default(), + workers: Default::default(), + next_worker_id: Default::default(), start_time: Instant::now(), - seeded_rng, + seeded_rng: fl.seed.map(|v| StdRng::seed_from_u64(v).into()), target_lib: TargetLib::Main, is_main: true, is_internal, - http_client, - })); - - Ok(Self(state)) + http_client: create_http_client(fl.ca_file.as_deref())?.into(), + }; + Ok(Rc::new(state)) } /// If `shared_permission` is None then permissions from globa state are used. pub fn new_for_worker( - global_state: GlobalState, + global_state: &Arc, shared_permissions: Option, main_module: ModuleSpecifier, - ) -> Result { - let seeded_rng = match global_state.flags.seed { - Some(seed) => Some(StdRng::seed_from_u64(seed)), - None => None, - }; - - let permissions = if let Some(perm) = shared_permissions { - perm - } else { - global_state.permissions.clone() - }; - - let http_client = create_http_client(global_state.flags.ca_file.clone())?; - - let state = Rc::new(RefCell::new(StateInner { - global_state, + ) -> Result, ErrBox> { + let fl = &global_state.flags; + let state = State { + global_state: global_state.clone(), main_module, - permissions, + permissions: shared_permissions + .unwrap_or_else(|| global_state.permissions.clone()) + .into(), import_map: None, - metrics: Metrics::default(), - global_timer: GlobalTimer::new(), - workers: HashMap::new(), - next_worker_id: 0, + metrics: Default::default(), + global_timer: Default::default(), + workers: Default::default(), + next_worker_id: Default::default(), start_time: Instant::now(), - seeded_rng, + seeded_rng: fl.seed.map(|v| StdRng::seed_from_u64(v).into()), target_lib: TargetLib::Worker, is_main: false, is_internal: false, - http_client, - })); - - Ok(Self(state)) + http_client: create_http_client(fl.ca_file.as_deref())?.into(), + }; + Ok(Rc::new(state)) } #[inline] pub fn check_read(&self, path: &Path) -> Result<(), OpError> { - self.borrow().permissions.check_read(path) + self.permissions.borrow().check_read(path) } /// As `check_read()`, but permission error messages will anonymize the path @@ -532,42 +500,42 @@ impl State { path: &Path, display: &str, ) -> Result<(), OpError> { - self.borrow().permissions.check_read_blind(path, display) + self.permissions.borrow().check_read_blind(path, display) } #[inline] pub fn check_write(&self, path: &Path) -> Result<(), OpError> { - self.borrow().permissions.check_write(path) + self.permissions.borrow().check_write(path) } #[inline] pub fn check_env(&self) -> Result<(), OpError> { - self.borrow().permissions.check_env() + self.permissions.borrow().check_env() } #[inline] pub fn check_net(&self, hostname: &str, port: u16) -> Result<(), OpError> { - self.borrow().permissions.check_net(hostname, port) + self.permissions.borrow().check_net(hostname, port) } #[inline] pub fn check_net_url(&self, url: &url::Url) -> Result<(), OpError> { - self.borrow().permissions.check_net_url(url) + self.permissions.borrow().check_net_url(url) } #[inline] pub fn check_run(&self) -> Result<(), OpError> { - self.borrow().permissions.check_run() + self.permissions.borrow().check_run() } #[inline] pub fn check_hrtime(&self) -> Result<(), OpError> { - self.borrow().permissions.check_hrtime() + self.permissions.borrow().check_hrtime() } #[inline] pub fn check_plugin(&self, filename: &Path) -> Result<(), OpError> { - self.borrow().permissions.check_plugin(filename) + self.permissions.borrow().check_plugin(filename) } pub fn check_dyn_import( @@ -599,11 +567,11 @@ impl State { } #[cfg(test)] - pub fn mock(main_module: &str) -> State { + pub fn mock(main_module: &str) -> Rc { let module_specifier = ModuleSpecifier::resolve_url_or_path(main_module) .expect("Invalid entry module"); State::new( - GlobalState::mock(vec!["deno".to_string()], None), + &GlobalState::mock(vec!["deno".to_string()], None), None, module_specifier, None, diff --git a/cli/tokio_util.rs b/cli/tokio_util.rs index 0e1257da7b..e477cd5eee 100644 --- a/cli/tokio_util.rs +++ b/cli/tokio_util.rs @@ -12,7 +12,7 @@ pub fn create_basic_runtime() -> tokio::runtime::Runtime { // TODO(ry) rename to run_local ? pub fn run_basic(future: F) -> R where - F: std::future::Future + 'static, + F: std::future::Future, { let mut rt = create_basic_runtime(); rt.block_on(future) diff --git a/cli/tsc.rs b/cli/tsc.rs index 41128948b5..f0b2e037be 100644 --- a/cli/tsc.rs +++ b/cli/tsc.rs @@ -46,6 +46,7 @@ use std::ops::Deref; use std::ops::DerefMut; use std::path::PathBuf; use std::pin::Pin; +use std::rc::Rc; use std::str; use std::sync::atomic::Ordering; use std::sync::Arc; @@ -131,9 +132,12 @@ pub struct CompilerWorker { } impl CompilerWorker { - pub fn new(name: String, startup_data: StartupData, state: State) -> Self { - let state_ = state.clone(); - let mut worker = Worker::new(name, startup_data, state_); + pub fn new( + name: String, + startup_data: StartupData, + state: &Rc, + ) -> Self { + let mut worker = Worker::new(name, startup_data, state); let response = Arc::new(Mutex::new(None)); { let isolate = &mut worker.isolate; @@ -199,21 +203,16 @@ lazy_static! { /// Create a new worker with snapshot of TS compiler and setup compiler's /// runtime. fn create_compiler_worker( - global_state: GlobalState, + global_state: &Arc, permissions: Permissions, ) -> CompilerWorker { // TODO(bartlomieju): these $deno$ specifiers should be unified for all subcommands // like 'eval', 'repl' let entry_point = ModuleSpecifier::resolve_url_or_path("./__$deno$ts_compiler.ts").unwrap(); - let worker_state = State::new( - global_state.clone(), - Some(permissions), - entry_point, - None, - true, - ) - .expect("Unable to create worker state"); + let worker_state = + State::new(&global_state, Some(permissions), entry_point, None, true) + .expect("Unable to create worker state"); // TODO(bartlomieju): this metric is never used anywhere // Count how many times we start the compiler worker. @@ -222,7 +221,7 @@ fn create_compiler_worker( let mut worker = CompilerWorker::new( "TS".to_string(), startup_data::compiler_isolate_init(), - worker_state, + &worker_state, ); worker .execute("globalThis.bootstrapCompilerRuntime()") @@ -545,7 +544,7 @@ impl TsCompiler { /// compiler. pub async fn compile( &self, - global_state: GlobalState, + global_state: &Arc, source_file: &SourceFile, target: TargetLib, permissions: Permissions, @@ -635,7 +634,7 @@ impl TsCompiler { /// all the dependencies for that module. pub async fn bundle( &self, - global_state: GlobalState, + global_state: &Arc, module_specifier: ModuleSpecifier, ) -> Result { debug!( @@ -1055,11 +1054,11 @@ impl TsCompiler { } async fn execute_in_same_thread( - global_state: GlobalState, + global_state: &Arc, permissions: Permissions, req: String, ) -> Result { - let mut worker = create_compiler_worker(global_state.clone(), permissions); + let mut worker = create_compiler_worker(&global_state, permissions); let script = format!("globalThis.tsCompilerOnMessage({{ data: {} }});", req); worker.execute2("", &script)?; (&mut *worker).await?; @@ -1067,7 +1066,7 @@ async fn execute_in_same_thread( } async fn create_runtime_module_graph( - global_state: GlobalState, + global_state: &Arc, permissions: Permissions, root_name: &str, sources: &Option>, @@ -1131,14 +1130,14 @@ fn js_error_to_op_error(error: ErrBox) -> OpError { /// This function is used by `Deno.compile()` API. pub async fn runtime_compile( - global_state: GlobalState, + global_state: &Arc, permissions: Permissions, root_name: &str, sources: &Option>, maybe_options: &Option, ) -> Result { let (root_names, module_graph) = create_runtime_module_graph( - global_state.clone(), + &global_state, permissions.clone(), root_name, sources, @@ -1178,14 +1177,14 @@ pub async fn runtime_compile( /// This function is used by `Deno.bundle()` API. pub async fn runtime_bundle( - global_state: GlobalState, + global_state: &Arc, permissions: Permissions, root_name: &str, sources: &Option>, maybe_options: &Option, ) -> Result { let (root_names, module_graph) = create_runtime_module_graph( - global_state.clone(), + &global_state, permissions.clone(), root_name, sources, @@ -1217,7 +1216,7 @@ pub async fn runtime_bundle( /// This function is used by `Deno.transpileOnly()` API. pub async fn runtime_transpile( - global_state: GlobalState, + global_state: &Arc, permissions: Permissions, sources: &HashMap, options: &Option, @@ -1495,6 +1494,7 @@ mod tests { use super::*; use crate::deno_dir; use crate::fs as deno_fs; + use crate::global_state::GlobalState; use crate::http_cache; use deno_core::ModuleSpecifier; use std::path::PathBuf; @@ -1607,7 +1607,7 @@ mod tests { let result = ts_compiler .compile( - mock_state.clone(), + &mock_state, &out, TargetLib::Main, Permissions::allow_all(), @@ -1716,7 +1716,7 @@ mod tests { let result = mock_state .ts_compiler - .bundle(mock_state.clone(), module_name) + .bundle(&mock_state, module_name) .await; assert!(result.is_ok()); diff --git a/cli/web_worker.rs b/cli/web_worker.rs index 9ac26fca0d..8d9c00499c 100644 --- a/cli/web_worker.rs +++ b/cli/web_worker.rs @@ -14,6 +14,7 @@ use std::future::Future; use std::ops::Deref; use std::ops::DerefMut; use std::pin::Pin; +use std::rc::Rc; use std::sync::atomic::AtomicBool; use std::sync::atomic::Ordering; use std::sync::Arc; @@ -84,11 +85,10 @@ impl WebWorker { pub fn new( name: String, startup_data: StartupData, - state: State, + state: &Rc, has_deno_namespace: bool, ) -> Self { - let state_ = state.clone(); - let mut worker = Worker::new(name, startup_data, state_); + let mut worker = Worker::new(name, startup_data, &state); let terminated = Arc::new(AtomicBool::new(false)); let isolate_handle = worker.isolate.thread_safe_handle(); @@ -254,7 +254,7 @@ mod tests { let mut worker = WebWorker::new( "TEST".to_string(), startup_data::deno_isolate_init(), - state, + &state, false, ); worker diff --git a/cli/worker.rs b/cli/worker.rs index 1e9b2fb4a8..928d3316fb 100644 --- a/cli/worker.rs +++ b/cli/worker.rs @@ -92,19 +92,23 @@ pub struct Worker { pub name: String, pub isolate: deno_core::EsIsolate, pub inspector: Option>, - pub state: State, + pub state: Rc, pub waker: AtomicWaker, pub(crate) internal_channels: WorkerChannelsInternal, external_channels: WorkerHandle, } impl Worker { - pub fn new(name: String, startup_data: StartupData, state: State) -> Self { - let loader = Rc::new(state.clone()); - let mut isolate = deno_core::EsIsolate::new(loader, startup_data, false); + pub fn new( + name: String, + startup_data: StartupData, + state: &Rc, + ) -> Self { + let mut isolate = + deno_core::EsIsolate::new(state.clone(), startup_data, false); { - let global_state = state.borrow().global_state.clone(); + let global_state = state.global_state.clone(); let core_state_rc = CoreIsolate::state(&isolate); let mut core_state = core_state_rc.borrow_mut(); core_state.set_js_error_create_fn(move |core_js_error| { @@ -113,7 +117,6 @@ impl Worker { } let inspector = { - let state = state.borrow(); let global_state = &state.global_state; global_state .flags @@ -129,7 +132,7 @@ impl Worker { name, isolate, inspector, - state, + state: state.clone(), waker: AtomicWaker::new(), internal_channels, external_channels, @@ -193,8 +196,7 @@ impl Worker { fn wait_for_inspector_session(&mut self) { let should_break_on_first_statement = self.inspector.is_some() && { - let state = self.state.borrow(); - state.is_main && state.global_state.flags.inspect_brk.is_some() + self.state.is_main && self.state.global_state.flags.inspect_brk.is_some() }; if should_break_on_first_statement { self @@ -250,9 +252,8 @@ pub struct MainWorker(Worker); impl MainWorker { // TODO(ry) combine MainWorker::new and MainWorker::create. - fn new(name: String, startup_data: StartupData, state: State) -> Self { - let state_ = state.clone(); - let mut worker = Worker::new(name, startup_data, state_); + fn new(name: String, startup_data: StartupData, state: &Rc) -> Self { + let mut worker = Worker::new(name, startup_data, state); { let isolate = &mut worker.isolate; ops::runtime::init(isolate, &state); @@ -281,11 +282,11 @@ impl MainWorker { } pub fn create( - global_state: GlobalState, + global_state: &Arc, main_module: ModuleSpecifier, ) -> Result { let state = State::new( - global_state.clone(), + &global_state, None, main_module, global_state.maybe_import_map.clone(), @@ -294,7 +295,7 @@ impl MainWorker { let mut worker = MainWorker::new( "main".to_string(), startup_data::deno_isolate_init(), - state, + &state, ); { let (stdin, stdout, stderr) = get_stdio(); @@ -335,7 +336,6 @@ mod tests { use crate::flags; use crate::global_state::GlobalState; use crate::startup_data; - use crate::state::State; use crate::tokio_util; use std::sync::atomic::Ordering; @@ -349,12 +349,11 @@ mod tests { ModuleSpecifier::resolve_url_or_path(&p.to_string_lossy()).unwrap(); let global_state = GlobalState::new(flags::Flags::default()).unwrap(); let state = - State::new(global_state, None, module_specifier.clone(), None, false) + State::new(&global_state, None, module_specifier.clone(), None, false) .unwrap(); - let state_ = state.clone(); - tokio_util::run_basic(async move { + tokio_util::run_basic(async { let mut worker = - MainWorker::new("TEST".to_string(), StartupData::None, state); + MainWorker::new("TEST".to_string(), StartupData::None, &state); let result = worker.execute_module(&module_specifier).await; if let Err(err) = result { eprintln!("execute_mod err {:?}", err); @@ -363,8 +362,7 @@ mod tests { panic!("Future got unexpected error: {:?}", e); } }); - let state = state_.borrow(); - assert_eq!(state.metrics.resolve_count, 2); + assert_eq!(state.metrics.borrow().resolve_count, 2); // Check that we didn't start the compiler. assert_eq!(state.global_state.compiler_starts.load(Ordering::SeqCst), 0); } @@ -379,12 +377,11 @@ mod tests { ModuleSpecifier::resolve_url_or_path(&p.to_string_lossy()).unwrap(); let global_state = GlobalState::new(flags::Flags::default()).unwrap(); let state = - State::new(global_state, None, module_specifier.clone(), None, false) + State::new(&global_state, None, module_specifier.clone(), None, false) .unwrap(); - let state_ = state.clone(); - tokio_util::run_basic(async move { + tokio_util::run_basic(async { let mut worker = - MainWorker::new("TEST".to_string(), StartupData::None, state); + MainWorker::new("TEST".to_string(), StartupData::None, &state); let result = worker.execute_module(&module_specifier).await; if let Err(err) = result { eprintln!("execute_mod err {:?}", err); @@ -394,7 +391,6 @@ mod tests { } }); - let state = state_.borrow(); // Check that we didn't start the compiler. assert_eq!(state.global_state.compiler_starts.load(Ordering::SeqCst), 0); } @@ -416,18 +412,13 @@ mod tests { ..flags::Flags::default() }; let global_state = GlobalState::new(flags).unwrap(); - let state = State::new( - global_state.clone(), - None, - module_specifier.clone(), - None, - false, - ) - .unwrap(); + let state = + State::new(&global_state, None, module_specifier.clone(), None, false) + .unwrap(); let mut worker = MainWorker::new( "TEST".to_string(), startup_data::deno_isolate_init(), - state.clone(), + &state, ); worker.execute("bootstrap.mainRuntime()").unwrap(); let result = worker.execute_module(&module_specifier).await; @@ -437,8 +428,7 @@ mod tests { if let Err(e) = (&mut *worker).await { panic!("Future got unexpected error: {:?}", e); } - let state = state.borrow(); - assert_eq!(state.metrics.resolve_count, 3); + assert_eq!(state.metrics.borrow().resolve_count, 3); // Check that we've only invoked the compiler once. assert_eq!(state.global_state.compiler_starts.load(Ordering::SeqCst), 1); } @@ -448,7 +438,7 @@ mod tests { let mut worker = MainWorker::new( "TEST".to_string(), startup_data::deno_isolate_init(), - state, + &state, ); worker.execute("bootstrap.mainRuntime()").unwrap(); worker