summaryrefslogtreecommitdiff
path: root/cli/state.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/state.rs')
-rw-r--r--cli/state.rs214
1 files changed, 91 insertions, 123 deletions
diff --git a/cli/state.rs b/cli/state.rs
index 5754e8c9d..055c09916 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<RefCell<StateInner>>);
-
-impl Deref for State {
- type Target = Rc<RefCell<StateInner>>;
- 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<GlobalState>,
+ pub permissions: RefCell<Permissions>,
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<ImportMap>,
- pub metrics: Metrics,
- pub global_timer: GlobalTimer,
- pub workers: HashMap<u32, (JoinHandle<()>, WebWorkerHandle)>,
- pub next_worker_id: u32,
+ pub metrics: RefCell<Metrics>,
+ pub global_timer: RefCell<GlobalTimer>,
+ pub workers: RefCell<HashMap<u32, (JoinHandle<()>, WebWorkerHandle)>>,
+ pub next_worker_id: Cell<u32>,
pub start_time: Instant,
- pub seeded_rng: Option<StdRng>,
+ pub seeded_rng: Option<RefCell<StdRng>>,
pub target_lib: TargetLib,
pub is_main: bool,
pub is_internal: bool,
- pub http_client: reqwest::Client,
+ pub http_client: RefCell<reqwest::Client>,
}
impl State {
pub fn stateful_json_op<D>(
- &self,
+ self: &Rc<Self>,
dispatcher: D,
) -> impl Fn(&mut deno_core::CoreIsolateState, &mut [ZeroCopyBuf]) -> Op
where
- D: Fn(&State, Value, &mut [ZeroCopyBuf]) -> Result<JsonOp, OpError>,
+ D: Fn(&Rc<State>, Value, &mut [ZeroCopyBuf]) -> Result<JsonOp, OpError>,
{
use crate::ops::json_op;
self.core_op(json_op(self.stateful_op(dispatcher)))
}
pub fn stateful_json_op_sync<D>(
- &self,
+ self: &Rc<Self>,
resource_table: &Rc<RefCell<ResourceTable>>,
dispatcher: D,
) -> impl Fn(&mut deno_core::CoreIsolateState, &mut [ZeroCopyBuf]) -> Op
@@ -117,12 +108,13 @@ impl State {
}
pub fn stateful_json_op_async<D, F>(
- &self,
+ self: &Rc<Self>,
resource_table: &Rc<RefCell<ResourceTable>>,
dispatcher: D,
) -> impl Fn(&mut CoreIsolateState, &mut [ZeroCopyBuf]) -> Op
where
- D: FnOnce(State, Rc<RefCell<ResourceTable>>, Value, BufVec) -> F + Clone,
+ D:
+ FnOnce(Rc<State>, Rc<RefCell<ResourceTable>>, Value, BufVec) -> F + Clone,
F: Future<Output = Result<Value, OpError>> + 'static,
{
let state = self.clone();
@@ -167,13 +159,13 @@ impl State {
}
pub fn stateful_json_op2<D>(
- &self,
+ self: &Rc<Self>,
dispatcher: D,
) -> impl Fn(&mut deno_core::CoreIsolateState, &mut [ZeroCopyBuf]) -> Op
where
D: Fn(
&mut deno_core::CoreIsolateState,
- &State,
+ &Rc<State>,
Value,
&mut [ZeroCopyBuf],
) -> Result<JsonOp, OpError>,
@@ -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<D>(
- &self,
+ self: &Rc<Self>,
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<D>(
- &self,
+ self: &Rc<Self>,
dispatcher: D,
) -> impl Fn(&mut deno_core::CoreIsolateState, &mut [ZeroCopyBuf]) -> Op
where
D: Fn(
&mut deno_core::CoreIsolateState,
- &State,
+ &Rc<State>,
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<D>(
- &self,
+ self: &Rc<Self>,
dispatcher: D,
) -> impl Fn(
&mut deno_core::CoreIsolateState,
@@ -284,7 +278,7 @@ impl State {
&mut [ZeroCopyBuf],
) -> Result<JsonOp, OpError>
where
- D: Fn(&State, Value, &mut [ZeroCopyBuf]) -> Result<JsonOp, OpError>,
+ D: Fn(&Rc<State>, Value, &mut [ZeroCopyBuf]) -> Result<JsonOp, OpError>,
{
let state = self.clone();
move |_isolate_state: &mut deno_core::CoreIsolateState,
@@ -294,7 +288,7 @@ impl State {
}
pub fn stateful_op2<D>(
- &self,
+ self: &Rc<Self>,
dispatcher: D,
) -> impl Fn(
&mut deno_core::CoreIsolateState,
@@ -304,7 +298,7 @@ impl State {
where
D: Fn(
&mut deno_core::CoreIsolateState,
- &State,
+ &Rc<State>,
Value,
&mut [ZeroCopyBuf],
) -> Result<JsonOp, OpError>,
@@ -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<Self>, 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<ModuleSpecifier, ErrBox> {
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<Box<deno_core::ModuleSourceFuture>> {
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<Box<dyn Future<Output = Result<(), ErrBox>>>> {
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 `<unknown>`.
@@ -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<GlobalState>,
shared_permissions: Option<Permissions>,
main_module: ModuleSpecifier,
maybe_import_map: Option<ImportMap>,
is_internal: bool,
- ) -> Result<Self, ErrBox> {
- 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<Rc<Self>, 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<GlobalState>,
shared_permissions: Option<Permissions>,
main_module: ModuleSpecifier,
- ) -> Result<Self, ErrBox> {
- 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<Rc<Self>, 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<State> {
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,