diff options
author | Bartek IwaĆczuk <biwanczuk@gmail.com> | 2020-09-20 01:17:35 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-09-20 01:17:35 +0200 |
commit | b657d743a22802b8232fbf558f2f00bf2942096f (patch) | |
tree | e3a3047e78b6bd9c9e3f551f99f5e80e32de079d /cli/state.rs | |
parent | aaa5e6613a739f8e2ff7579b69c2504bcdc37d4f (diff) |
refactor: remove CliState, use OpState, add CliModuleLoader (#7588)
- remove "CliState.workers" and "CliState.next_worker_id", instead
store them on "OpState" using type aliases.
- remove "CliState.global_timer" and "CliState.start_time", instead
store them on "OpState" using type aliases.
- remove "CliState.is_internal", instead pass it to Worker::new
- move "CliState::permissions" to "OpState"
- move "CliState::main_module" to "OpState"
- move "CliState::global_state" to "OpState"
- move "CliState::check_unstable()" to "GlobalState"
- change "cli_state()" to "global_state()"
- change "deno_core::ModuleLoader" trait to pass "OpState" to callbacks
- rename "CliState" to "CliModuleLoader"
Diffstat (limited to 'cli/state.rs')
-rw-r--r-- | cli/state.rs | 227 |
1 files changed, 31 insertions, 196 deletions
diff --git a/cli/state.rs b/cli/state.rs index 37352e263..dcf540d09 100644 --- a/cli/state.rs +++ b/cli/state.rs @@ -1,58 +1,49 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -use crate::file_fetcher::SourceFileFetcher; use crate::global_state::GlobalState; use crate::import_map::ImportMap; use crate::permissions::Permissions; use crate::tsc::TargetLib; -use crate::web_worker::WebWorkerHandle; use deno_core::error::AnyError; -use deno_core::url; use deno_core::ModuleLoadId; use deno_core::ModuleLoader; use deno_core::ModuleSpecifier; +use deno_core::OpState; use futures::future::FutureExt; use futures::Future; -use std::cell::Cell; use std::cell::RefCell; -use std::collections::HashMap; -use std::path::Path; -use std::path::PathBuf; use std::pin::Pin; use std::rc::Rc; use std::str; use std::sync::Arc; -use std::thread::JoinHandle; -use std::time::Instant; -// This is named "CliState" instead of just "State" to avoid confusion with all -// other state structs (GlobalState, OpState, GothamState). -// TODO(ry) Many of the items in this struct should be moved out and into -// OpState, removing redundant RefCell wrappers if possible. -pub struct CliState { - pub global_state: Arc<GlobalState>, - pub permissions: RefCell<Permissions>, - pub main_module: ModuleSpecifier, +pub struct CliModuleLoader { /// When flags contains a `.import_map_path` option, the content of the /// import map file will be resolved and set. pub import_map: Option<ImportMap>, - pub workers: RefCell<HashMap<u32, (JoinHandle<()>, WebWorkerHandle)>>, - pub next_worker_id: Cell<u32>, - pub start_time: Instant, pub target_lib: TargetLib, pub is_main: bool, - pub is_internal: bool, } -pub fn exit_unstable(api_name: &str) { - eprintln!( - "Unstable API '{}'. The --unstable flag must be provided.", - api_name - ); - std::process::exit(70); +impl CliModuleLoader { + pub fn new(maybe_import_map: Option<ImportMap>) -> Rc<Self> { + Rc::new(CliModuleLoader { + import_map: maybe_import_map, + target_lib: TargetLib::Main, + is_main: true, + }) + } + + pub fn new_for_worker() -> Rc<Self> { + Rc::new(CliModuleLoader { + import_map: None, + target_lib: TargetLib::Worker, + is_main: false, + }) + } } -impl ModuleLoader for CliState { +impl ModuleLoader for CliModuleLoader { fn resolve( &self, specifier: &str, @@ -75,13 +66,17 @@ impl ModuleLoader for CliState { fn load( &self, + op_state: Rc<RefCell<OpState>>, module_specifier: &ModuleSpecifier, maybe_referrer: Option<ModuleSpecifier>, _is_dyn_import: bool, ) -> Pin<Box<deno_core::ModuleSourceFuture>> { let module_specifier = module_specifier.to_owned(); let module_url_specified = module_specifier.to_string(); - let global_state = self.global_state.clone(); + let global_state = { + let state = op_state.borrow(); + state.borrow::<Arc<GlobalState>>().clone() + }; // TODO(bartlomieju): `fetch_compiled_module` should take `load_id` param let fut = async move { @@ -102,6 +97,7 @@ impl ModuleLoader for CliState { fn prepare_load( &self, + op_state: Rc<RefCell<OpState>>, _load_id: ModuleLoadId, module_specifier: &ModuleSpecifier, maybe_referrer: Option<String>, @@ -110,15 +106,19 @@ impl ModuleLoader for CliState { let module_specifier = module_specifier.clone(); let target_lib = self.target_lib.clone(); let maybe_import_map = self.import_map.clone(); + let state = op_state.borrow(); + // 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 self.is_main && !is_dyn_import { Permissions::allow_all() } else { - self.permissions.borrow().clone() + state.borrow::<Permissions>().clone() }; - let global_state = self.global_state.clone(); + let global_state = state.borrow::<Arc<GlobalState>>().clone(); + drop(state); + // 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 `<unknown>`. @@ -144,168 +144,3 @@ impl ModuleLoader for CliState { .boxed_local() } } - -impl CliState { - /// If `shared_permission` is None then permissions from globa state are used. - pub fn new( - global_state: &Arc<GlobalState>, - shared_permissions: Option<Permissions>, - main_module: ModuleSpecifier, - maybe_import_map: Option<ImportMap>, - is_internal: bool, - ) -> Result<Rc<Self>, AnyError> { - let state = CliState { - global_state: global_state.clone(), - main_module, - permissions: shared_permissions - .unwrap_or_else(|| global_state.permissions.clone()) - .into(), - import_map: maybe_import_map, - workers: Default::default(), - next_worker_id: Default::default(), - start_time: Instant::now(), - target_lib: TargetLib::Main, - is_main: true, - is_internal, - }; - Ok(Rc::new(state)) - } - - /// If `shared_permission` is None then permissions from globa state are used. - pub fn new_for_worker( - global_state: &Arc<GlobalState>, - shared_permissions: Option<Permissions>, - main_module: ModuleSpecifier, - ) -> Result<Rc<Self>, AnyError> { - let state = CliState { - global_state: global_state.clone(), - main_module, - permissions: shared_permissions - .unwrap_or_else(|| global_state.permissions.clone()) - .into(), - import_map: None, - workers: Default::default(), - next_worker_id: Default::default(), - start_time: Instant::now(), - target_lib: TargetLib::Worker, - is_main: false, - is_internal: false, - }; - Ok(Rc::new(state)) - } - - #[inline] - pub fn check_read(&self, path: &Path) -> Result<(), AnyError> { - self.permissions.borrow().check_read(path) - } - - /// As `check_read()`, but permission error messages will anonymize the path - /// by replacing it with the given `display`. - #[inline] - pub fn check_read_blind( - &self, - path: &Path, - display: &str, - ) -> Result<(), AnyError> { - self.permissions.borrow().check_read_blind(path, display) - } - - #[inline] - pub fn check_write(&self, path: &Path) -> Result<(), AnyError> { - self.permissions.borrow().check_write(path) - } - - #[inline] - pub fn check_env(&self) -> Result<(), AnyError> { - self.permissions.borrow().check_env() - } - - #[inline] - pub fn check_net(&self, hostname: &str, port: u16) -> Result<(), AnyError> { - self.permissions.borrow().check_net(hostname, port) - } - - #[inline] - pub fn check_net_url(&self, url: &url::Url) -> Result<(), AnyError> { - self.permissions.borrow().check_net_url(url) - } - - #[inline] - pub fn check_run(&self) -> Result<(), AnyError> { - self.permissions.borrow().check_run() - } - - #[inline] - pub fn check_hrtime(&self) -> Result<(), AnyError> { - self.permissions.borrow().check_hrtime() - } - - #[inline] - pub fn check_plugin(&self, filename: &Path) -> Result<(), AnyError> { - self.permissions.borrow().check_plugin(filename) - } - - pub fn check_dyn_import( - &self, - module_specifier: &ModuleSpecifier, - ) -> Result<(), AnyError> { - let u = module_specifier.as_url(); - // TODO(bartlomieju): temporary fix to prevent hitting `unreachable` - // statement that is actually reachable... - SourceFileFetcher::check_if_supported_scheme(u)?; - - match u.scheme() { - "http" | "https" => { - self.check_net_url(u)?; - Ok(()) - } - "file" => { - let path = u - .to_file_path() - .unwrap() - .into_os_string() - .into_string() - .unwrap(); - self.check_read(Path::new(&path))?; - Ok(()) - } - _ => unreachable!(), - } - } - - #[cfg(test)] - pub fn mock(main_module: &str) -> Rc<Self> { - let module_specifier = ModuleSpecifier::resolve_url_or_path(main_module) - .expect("Invalid entry module"); - CliState::new( - &GlobalState::mock(vec!["deno".to_string()], None), - None, - module_specifier, - None, - false, - ) - .unwrap() - } - - /// 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. - pub fn check_unstable(&self, api_name: &str) { - // TODO(ry) Maybe use IsolateHandle::terminate_execution here to provide a - // stack trace in JS. - if !self.global_state.flags.unstable { - exit_unstable(api_name); - } - } -} - -impl deno_fetch::FetchPermissions for CliState { - fn check_net_url(&self, url: &url::Url) -> Result<(), AnyError> { - CliState::check_net_url(self, url) - } - - fn check_read(&self, p: &PathBuf) -> Result<(), AnyError> { - CliState::check_read(self, p) - } -} |