summaryrefslogtreecommitdiff
path: root/cli
diff options
context:
space:
mode:
Diffstat (limited to 'cli')
-rw-r--r--cli/global_state.rs19
-rw-r--r--cli/global_timer.rs46
-rw-r--r--cli/main.rs2
-rw-r--r--cli/ops/errors.rs2
-rw-r--r--cli/ops/fetch.rs6
-rw-r--r--cli/ops/fs.rs209
-rw-r--r--cli/ops/fs_events.rs5
-rw-r--r--cli/ops/mod.rs10
-rw-r--r--cli/ops/net.rs38
-rw-r--r--cli/ops/os.rs34
-rw-r--r--cli/ops/permissions.rs10
-rw-r--r--cli/ops/plugin.rs6
-rw-r--r--cli/ops/process.rs12
-rw-r--r--cli/ops/repl.rs4
-rw-r--r--cli/ops/runtime.rs10
-rw-r--r--cli/ops/runtime_compiler.rs19
-rw-r--r--cli/ops/signal.rs6
-rw-r--r--cli/ops/timers.rs56
-rw-r--r--cli/ops/tls.rs24
-rw-r--r--cli/ops/tty.rs4
-rw-r--r--cli/ops/websocket.rs11
-rw-r--r--cli/ops/worker_host.rs52
-rw-r--r--cli/permissions.rs10
-rw-r--r--cli/state.rs227
-rw-r--r--cli/tsc.rs34
-rw-r--r--cli/web_worker.rs36
-rw-r--r--cli/worker.rs118
27 files changed, 506 insertions, 504 deletions
diff --git a/cli/global_state.rs b/cli/global_state.rs
index 700909f8f..52bf48593 100644
--- a/cli/global_state.rs
+++ b/cli/global_state.rs
@@ -10,7 +10,6 @@ use crate::media_type::MediaType;
use crate::module_graph::ModuleGraphFile;
use crate::module_graph::ModuleGraphLoader;
use crate::permissions::Permissions;
-use crate::state::exit_unstable;
use crate::tsc::CompiledModule;
use crate::tsc::TargetLib;
use crate::tsc::TsCompiler;
@@ -22,6 +21,14 @@ use std::sync::Arc;
use std::sync::Mutex;
use tokio::sync::Mutex as AsyncMutex;
+pub fn exit_unstable(api_name: &str) {
+ eprintln!(
+ "Unstable API '{}'. The --unstable flag must be provided.",
+ api_name
+ );
+ std::process::exit(70);
+}
+
/// This structure represents state of single "deno" program.
///
/// It is shared by all created workers (thus V8 isolates).
@@ -235,6 +242,16 @@ impl GlobalState {
Ok(compiled_module)
}
+ /// 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) {
+ if !self.flags.unstable {
+ exit_unstable(api_name);
+ }
+ }
+
#[cfg(test)]
pub fn mock(
argv: Vec<String>,
diff --git a/cli/global_timer.rs b/cli/global_timer.rs
index bf335bff0..6fad563a2 100644
--- a/cli/global_timer.rs
+++ b/cli/global_timer.rs
@@ -1,47 +1 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
-
-//! This module helps deno implement timers.
-//!
-//! As an optimization, we want to avoid an expensive calls into rust for every
-//! setTimeout in JavaScript. Thus in //js/timers.ts a data structure is
-//! implemented that calls into Rust for only the smallest timeout. Thus we
-//! only need to be able to start and cancel a single timer (or Delay, as Tokio
-//! calls it) for an entire Isolate. This is what is implemented here.
-
-use futures::channel::oneshot;
-use futures::future::FutureExt;
-use futures::TryFutureExt;
-use std::future::Future;
-use std::time::Instant;
-
-#[derive(Default)]
-pub struct GlobalTimer {
- tx: Option<oneshot::Sender<()>>,
-}
-
-impl GlobalTimer {
- pub fn cancel(&mut self) {
- if let Some(tx) = self.tx.take() {
- tx.send(()).ok();
- }
- }
-
- pub fn new_timeout(
- &mut self,
- deadline: Instant,
- ) -> impl Future<Output = Result<(), ()>> {
- if self.tx.is_some() {
- self.cancel();
- }
- assert!(self.tx.is_none());
-
- let (tx, rx) = oneshot::channel();
- self.tx = Some(tx);
-
- let delay = tokio::time::delay_until(deadline.into());
- let rx = rx
- .map_err(|err| panic!("Unexpected error in receiving channel {:?}", err));
-
- futures::future::select(delay, rx).then(|_| futures::future::ok(()))
- }
-}
diff --git a/cli/main.rs b/cli/main.rs
index 2d80372c7..f45586c61 100644
--- a/cli/main.rs
+++ b/cli/main.rs
@@ -78,9 +78,9 @@ use flags::DenoSubcommand;
use flags::Flags;
use futures::future::FutureExt;
use futures::Future;
+use global_state::exit_unstable;
use log::Level;
use log::LevelFilter;
-use state::exit_unstable;
use std::env;
use std::io::Read;
use std::io::Write;
diff --git a/cli/ops/errors.rs b/cli/ops/errors.rs
index 5012b0db0..6bf0983e2 100644
--- a/cli/ops/errors.rs
+++ b/cli/ops/errors.rs
@@ -37,7 +37,7 @@ fn op_apply_source_map(
args.line_number.into(),
args.column_number.into(),
&mut mappings_map,
- &super::cli_state(state).global_state.ts_compiler,
+ &super::global_state(state).ts_compiler,
);
Ok(json!({
diff --git a/cli/ops/fetch.rs b/cli/ops/fetch.rs
index cbfcfb874..54585dc3d 100644
--- a/cli/ops/fetch.rs
+++ b/cli/ops/fetch.rs
@@ -1,12 +1,12 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
-use crate::state::CliState;
+use crate::permissions::Permissions;
pub fn init(rt: &mut deno_core::JsRuntime) {
- super::reg_json_async(rt, "op_fetch", deno_fetch::op_fetch::<CliState>);
+ super::reg_json_async(rt, "op_fetch", deno_fetch::op_fetch::<Permissions>);
super::reg_json_async(rt, "op_fetch_read", deno_fetch::op_fetch_read);
super::reg_json_sync(
rt,
"op_create_http_client",
- deno_fetch::op_create_http_client::<CliState>,
+ deno_fetch::op_create_http_client::<Permissions>,
);
}
diff --git a/cli/ops/fs.rs b/cli/ops/fs.rs
index 5189d7099..ad5cc8add 100644
--- a/cli/ops/fs.rs
+++ b/cli/ops/fs.rs
@@ -2,6 +2,7 @@
// Some deserializer fields are only used on Unix and Windows build fails without it
use super::io::std_file_resource;
use super::io::{FileMetadata, StreamResource, StreamResourceHolder};
+use crate::permissions::Permissions;
use deno_core::error::custom_error;
use deno_core::error::type_error;
use deno_core::error::AnyError;
@@ -151,15 +152,15 @@ fn open_helper(
let _ = mode; // avoid unused warning
}
+ let permissions = state.borrow::<Permissions>();
let options = args.options;
+
if options.read {
- let cli_state = super::cli_state(state);
- cli_state.check_read(&path)?;
+ permissions.check_read(&path)?;
}
if options.write || options.append {
- let cli_state = super::cli_state(state);
- cli_state.check_write(&path)?;
+ permissions.check_write(&path)?;
}
open_options
@@ -280,7 +281,7 @@ fn op_fdatasync_sync(
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
{
- let cli_state = super::cli_state(state);
+ let cli_state = super::global_state(state);
cli_state.check_unstable("Deno.fdatasync");
}
let args: FdatasyncArgs = serde_json::from_value(args)?;
@@ -297,7 +298,7 @@ async fn op_fdatasync_async(
args: Value,
_zero_copy: BufVec,
) -> Result<Value, AnyError> {
- super::cli_state2(&state).check_unstable("Deno.fdatasync");
+ super::global_state2(&state).check_unstable("Deno.fdatasync");
let args: FdatasyncArgs = serde_json::from_value(args)?;
let rid = args.rid as u32;
@@ -320,7 +321,7 @@ fn op_fsync_sync(
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
{
- let cli_state = super::cli_state(state);
+ let cli_state = super::global_state(state);
cli_state.check_unstable("Deno.fsync");
}
let args: FsyncArgs = serde_json::from_value(args)?;
@@ -337,7 +338,7 @@ async fn op_fsync_async(
args: Value,
_zero_copy: BufVec,
) -> Result<Value, AnyError> {
- super::cli_state2(&state).check_unstable("Deno.fsync");
+ super::global_state2(&state).check_unstable("Deno.fsync");
let args: FsyncArgs = serde_json::from_value(args)?;
let rid = args.rid as u32;
@@ -360,7 +361,7 @@ fn op_fstat_sync(
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
{
- let cli_state = super::cli_state(state);
+ let cli_state = super::global_state(state);
cli_state.check_unstable("Deno.fstat");
}
let args: FstatArgs = serde_json::from_value(args)?;
@@ -377,7 +378,7 @@ async fn op_fstat_async(
args: Value,
_zero_copy: BufVec,
) -> Result<Value, AnyError> {
- super::cli_state2(&state).check_unstable("Deno.fstat");
+ super::global_state2(&state).check_unstable("Deno.fstat");
let args: FstatArgs = serde_json::from_value(args)?;
let rid = args.rid as u32;
@@ -402,7 +403,7 @@ fn op_umask(
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
{
- let cli_state = super::cli_state(state);
+ let cli_state = super::global_state(state);
cli_state.check_unstable("Deno.umask");
}
let args: UmaskArgs = serde_json::from_value(args)?;
@@ -444,8 +445,7 @@ fn op_chdir(
) -> Result<Value, AnyError> {
let args: ChdirArgs = serde_json::from_value(args)?;
let d = PathBuf::from(&args.directory);
- let cli_state = super::cli_state(state);
- cli_state.check_read(&d)?;
+ state.borrow::<Permissions>().check_read(&d)?;
set_current_dir(&d)?;
Ok(json!({}))
}
@@ -466,8 +466,7 @@ fn op_mkdir_sync(
let args: MkdirArgs = serde_json::from_value(args)?;
let path = Path::new(&args.path).to_path_buf();
let mode = args.mode.unwrap_or(0o777) & 0o777;
- let cli_state = super::cli_state(state);
- cli_state.check_write(&path)?;
+ state.borrow::<Permissions>().check_write(&path)?;
debug!("op_mkdir {} {:o} {}", path.display(), mode, args.recursive);
let mut builder = std::fs::DirBuilder::new();
builder.recursive(args.recursive);
@@ -489,7 +488,10 @@ async fn op_mkdir_async(
let path = Path::new(&args.path).to_path_buf();
let mode = args.mode.unwrap_or(0o777) & 0o777;
- super::cli_state2(&state).check_write(&path)?;
+ {
+ let state = state.borrow();
+ state.borrow::<Permissions>().check_write(&path)?;
+ }
tokio::task::spawn_blocking(move || {
debug!("op_mkdir {} {:o} {}", path.display(), mode, args.recursive);
@@ -523,8 +525,7 @@ fn op_chmod_sync(
let path = Path::new(&args.path).to_path_buf();
let mode = args.mode & 0o777;
- let cli_state = super::cli_state(state);
- cli_state.check_write(&path)?;
+ state.borrow::<Permissions>().check_write(&path)?;
debug!("op_chmod_sync {} {:o}", path.display(), mode);
#[cfg(unix)]
{
@@ -551,7 +552,10 @@ async fn op_chmod_async(
let path = Path::new(&args.path).to_path_buf();
let mode = args.mode & 0o777;
- super::cli_state2(&state).check_write(&path)?;
+ {
+ let state = state.borrow();
+ state.borrow::<Permissions>().check_write(&path)?;
+ }
tokio::task::spawn_blocking(move || {
debug!("op_chmod_async {} {:o}", path.display(), mode);
@@ -589,8 +593,7 @@ fn op_chown_sync(
) -> Result<Value, AnyError> {
let args: ChownArgs = serde_json::from_value(args)?;
let path = Path::new(&args.path).to_path_buf();
- let cli_state = super::cli_state(state);
- cli_state.check_write(&path)?;
+ state.borrow::<Permissions>().check_write(&path)?;
debug!(
"op_chown_sync {} {:?} {:?}",
path.display(),
@@ -620,7 +623,10 @@ async fn op_chown_async(
let args: ChownArgs = serde_json::from_value(args)?;
let path = Path::new(&args.path).to_path_buf();
- super::cli_state2(&state).check_write(&path)?;
+ {
+ let state = state.borrow();
+ state.borrow::<Permissions>().check_write(&path)?;
+ }
tokio::task::spawn_blocking(move || {
debug!(
@@ -661,8 +667,7 @@ fn op_remove_sync(
let path = PathBuf::from(&args.path);
let recursive = args.recursive;
- let cli_state = super::cli_state(state);
- cli_state.check_write(&path)?;
+ state.borrow::<Permissions>().check_write(&path)?;
#[cfg(not(unix))]
use std::os::windows::prelude::MetadataExt;
@@ -705,7 +710,10 @@ async fn op_remove_async(
let path = PathBuf::from(&args.path);
let recursive = args.recursive;
- super::cli_state2(&state).check_write(&path)?;
+ {
+ let state = state.borrow();
+ state.borrow::<Permissions>().check_write(&path)?;
+ }
tokio::task::spawn_blocking(move || {
#[cfg(not(unix))]
@@ -759,9 +767,9 @@ fn op_copy_file_sync(
let from = PathBuf::from(&args.from);
let to = PathBuf::from(&args.to);
- let cli_state = super::cli_state(state);
- cli_state.check_read(&from)?;
- cli_state.check_write(&to)?;
+ let permissions = state.borrow::<Permissions>();
+ permissions.check_read(&from)?;
+ permissions.check_write(&to)?;
debug!("op_copy_file_sync {} {}", from.display(), to.display());
// On *nix, Rust reports non-existent `from` as ErrorKind::InvalidInput
@@ -785,9 +793,12 @@ async fn op_copy_file_async(
let from = PathBuf::from(&args.from);
let to = PathBuf::from(&args.to);
- let cli_state = super::cli_state2(&state);
- cli_state.check_read(&from)?;
- cli_state.check_write(&to)?;
+ {
+ let state = state.borrow();
+ let permissions = state.borrow::<Permissions>();
+ permissions.check_read(&from)?;
+ permissions.check_write(&to)?;
+ }
debug!("op_copy_file_async {} {}", from.display(), to.display());
tokio::task::spawn_blocking(move || {
@@ -879,8 +890,7 @@ fn op_stat_sync(
let args: StatArgs = serde_json::from_value(args)?;
let path = PathBuf::from(&args.path);
let lstat = args.lstat;
- let cli_state = super::cli_state(state);
- cli_state.check_read(&path)?;
+ state.borrow::<Permissions>().check_read(&path)?;
debug!("op_stat_sync {} {}", path.display(), lstat);
let metadata = if lstat {
std::fs::symlink_metadata(&path)?
@@ -899,7 +909,10 @@ async fn op_stat_async(
let path = PathBuf::from(&args.path);
let lstat = args.lstat;
- super::cli_state2(&state).check_read(&path)?;
+ {
+ let state = state.borrow();
+ state.borrow::<Permissions>().check_read(&path)?;
+ }
tokio::task::spawn_blocking(move || {
debug!("op_stat_async {} {}", path.display(), lstat);
@@ -928,10 +941,10 @@ fn op_realpath_sync(
let args: RealpathArgs = serde_json::from_value(args)?;
let path = PathBuf::from(&args.path);
- let cli_state = super::cli_state(state);
- cli_state.check_read(&path)?;
+ let permissions = state.borrow::<Permissions>();
+ permissions.check_read(&path)?;
if path.is_relative() {
- cli_state.check_read_blind(&current_dir()?, "CWD")?;
+ permissions.check_read_blind(&current_dir()?, "CWD")?;
}
debug!("op_realpath_sync {}", path.display());
@@ -954,10 +967,13 @@ async fn op_realpath_async(
let args: RealpathArgs = serde_json::from_value(args)?;
let path = PathBuf::from(&args.path);
- let cli_state = super::cli_state2(&state);
- cli_state.check_read(&path)?;
- if path.is_relative() {
- cli_state.check_read_blind(&current_dir()?, "CWD")?;
+ {
+ let state = state.borrow();
+ let permissions = state.borrow::<Permissions>();
+ permissions.check_read(&path)?;
+ if path.is_relative() {
+ permissions.check_read_blind(&current_dir()?, "CWD")?;
+ }
}
tokio::task::spawn_blocking(move || {
@@ -990,8 +1006,7 @@ fn op_read_dir_sync(
let args: ReadDirArgs = serde_json::from_value(args)?;
let path = PathBuf::from(&args.path);
- let cli_state = super::cli_state(state);
- cli_state.check_read(&path)?;
+ state.borrow::<Permissions>().check_read(&path)?;
debug!("op_read_dir_sync {}", path.display());
let entries: Vec<_> = std::fs::read_dir(path)?
@@ -1022,7 +1037,10 @@ async fn op_read_dir_async(
) -> Result<Value, AnyError> {
let args: ReadDirArgs = serde_json::from_value(args)?;
let path = PathBuf::from(&args.path);
- super::cli_state2(&state).check_read(&path)?;
+ {
+ let state = state.borrow();
+ state.borrow::<Permissions>().check_read(&path)?;
+ }
tokio::task::spawn_blocking(move || {
debug!("op_read_dir_async {}", path.display());
let entries: Vec<_> = std::fs::read_dir(path)?
@@ -1065,10 +1083,10 @@ fn op_rename_sync(
let oldpath = PathBuf::from(&args.oldpath);
let newpath = PathBuf::from(&args.newpath);
- let cli_state = super::cli_state(state);
- cli_state.check_read(&oldpath)?;
- cli_state.check_write(&oldpath)?;
- cli_state.check_write(&newpath)?;
+ let permissions = state.borrow::<Permissions>();
+ permissions.check_read(&oldpath)?;
+ permissions.check_write(&oldpath)?;
+ permissions.check_write(&newpath)?;
debug!("op_rename_sync {} {}", oldpath.display(), newpath.display());
std::fs::rename(&oldpath, &newpath)?;
Ok(json!({}))
@@ -1083,10 +1101,11 @@ async fn op_rename_async(
let oldpath = PathBuf::from(&args.oldpath);
let newpath = PathBuf::from(&args.newpath);
{
- let cli_state = super::cli_state2(&state);
- cli_state.check_read(&oldpath)?;
- cli_state.check_write(&oldpath)?;
- cli_state.check_write(&newpath)?;
+ let state = state.borrow();
+ let permissions = state.borrow::<Permissions>();
+ permissions.check_read(&oldpath)?;
+ permissions.check_write(&oldpath)?;
+ permissions.check_write(&newpath)?;
}
tokio::task::spawn_blocking(move || {
debug!(
@@ -1113,14 +1132,15 @@ fn op_link_sync(
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
- let cli_state = super::cli_state(state);
+ let cli_state = super::global_state(state);
cli_state.check_unstable("Deno.link");
let args: LinkArgs = serde_json::from_value(args)?;
let oldpath = PathBuf::from(&args.oldpath);
let newpath = PathBuf::from(&args.newpath);
- cli_state.check_read(&oldpath)?;
- cli_state.check_write(&newpath)?;
+ let permissions = state.borrow::<Permissions>();
+ permissions.check_read(&oldpath)?;
+ permissions.check_write(&newpath)?;
debug!("op_link_sync {} {}", oldpath.display(), newpath.display());
std::fs::hard_link(&oldpath, &newpath)?;
@@ -1132,15 +1152,19 @@ async fn op_link_async(
args: Value,
_zero_copy: BufVec,
) -> Result<Value, AnyError> {
- let cli_state = super::cli_state2(&state);
+ let cli_state = super::global_state2(&state);
cli_state.check_unstable("Deno.link");
let args: LinkArgs = serde_json::from_value(args)?;
let oldpath = PathBuf::from(&args.oldpath);
let newpath = PathBuf::from(&args.newpath);
- cli_state.check_read(&oldpath)?;
- cli_state.check_write(&newpath)?;
+ {
+ let state = state.borrow();
+ let permissions = state.borrow::<Permissions>();
+ permissions.check_read(&oldpath)?;
+ permissions.check_write(&newpath)?;
+ }
tokio::task::spawn_blocking(move || {
debug!("op_link_async {} {}", oldpath.display(), newpath.display());
@@ -1172,13 +1196,13 @@ fn op_symlink_sync(
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
- let cli_state = super::cli_state(state);
+ let cli_state = super::global_state(state);
cli_state.check_unstable("Deno.symlink");
let args: SymlinkArgs = serde_json::from_value(args)?;
let oldpath = PathBuf::from(&args.oldpath);
let newpath = PathBuf::from(&args.newpath);
- cli_state.check_write(&newpath)?;
+ state.borrow::<Permissions>().check_write(&newpath)?;
debug!(
"op_symlink_sync {} {}",
@@ -1224,14 +1248,17 @@ async fn op_symlink_async(
args: Value,
_zero_copy: BufVec,
) -> Result<Value, AnyError> {
- let cli_state = super::cli_state2(&state);
+ let cli_state = super::global_state2(&state);
cli_state.check_unstable("Deno.symlink");
let args: SymlinkArgs = serde_json::from_value(args)?;
let oldpath = PathBuf::from(&args.oldpath);
let newpath = PathBuf::from(&args.newpath);
- cli_state.check_write(&newpath)?;
+ {
+ let state = state.borrow();
+ state.borrow::<Permissions>().check_write(&newpath)?;
+ }
tokio::task::spawn_blocking(move || {
debug!("op_symlink_async {} {}", oldpath.display(), newpath.display());
@@ -1286,8 +1313,7 @@ fn op_read_link_sync(
let args: ReadLinkArgs = serde_json::from_value(args)?;
let path = PathBuf::from(&args.path);
- let cli_state = super::cli_state(state);
- cli_state.check_read(&path)?;
+ state.borrow::<Permissions>().check_read(&path)?;
debug!("op_read_link_value {}", path.display());
let target = std::fs::read_link(&path)?.into_os_string();
@@ -1302,7 +1328,10 @@ async fn op_read_link_async(
) -> Result<Value, AnyError> {
let args: ReadLinkArgs = serde_json::from_value(args)?;
let path = PathBuf::from(&args.path);
- super::cli_state2(&state).check_read(&path)?;
+ {
+ let state = state.borrow();
+ state.borrow::<Permissions>().check_read(&path)?;
+ }
tokio::task::spawn_blocking(move || {
debug!("op_read_link_async {}", path.display());
let target = std::fs::read_link(&path)?.into_os_string();
@@ -1326,7 +1355,7 @@ fn op_ftruncate_sync(
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
{
- let cli_state = super::cli_state(state);
+ let cli_state = super::global_state(state);
cli_state.check_unstable("Deno.ftruncate");
}
let args: FtruncateArgs = serde_json::from_value(args)?;
@@ -1344,7 +1373,7 @@ async fn op_ftruncate_async(
args: Value,
_zero_copy: BufVec,
) -> Result<Value, AnyError> {
- super::cli_state2(&state).check_unstable("Deno.ftruncate");
+ super::global_state2(&state).check_unstable("Deno.ftruncate");
let args: FtruncateArgs = serde_json::from_value(args)?;
let rid = args.rid as u32;
let len = args.len as u64;
@@ -1371,8 +1400,7 @@ fn op_truncate_sync(
let path = PathBuf::from(&args.path);
let len = args.len;
- let cli_state = super::cli_state(state);
- cli_state.check_write(&path)?;
+ state.borrow::<Permissions>().check_write(&path)?;
debug!("op_truncate_sync {} {}", path.display(), len);
let f = std::fs::OpenOptions::new().write(true).open(&path)?;
@@ -1388,7 +1416,10 @@ async fn op_truncate_async(
let args: TruncateArgs = serde_json::from_value(args)?;
let path = PathBuf::from(&args.path);
let len = args.len;
- super::cli_state2(&state).check_write(&path)?;
+ {
+ let state = state.borrow();
+ state.borrow::<Permissions>().check_write(&path)?;
+ }
tokio::task::spawn_blocking(move || {
debug!("op_truncate_async {} {}", path.display(), len);
let f = std::fs::OpenOptions::new().write(true).open(&path)?;
@@ -1463,8 +1494,9 @@ fn op_make_temp_dir_sync(
let prefix = args.prefix.map(String::from);
let suffix = args.suffix.map(String::from);
- let cli_state = super::cli_state(state);
- cli_state.check_write(dir.clone().unwrap_or_else(temp_dir).as_path())?;
+ state
+ .borrow::<Permissions>()
+ .check_write(dir.clone().unwrap_or_else(temp_dir).as_path())?;
// TODO(piscisaureus): use byte vector for paths, not a string.
// See https://github.com/denoland/deno/issues/627.
@@ -1492,8 +1524,10 @@ async fn op_make_temp_dir_async(
let prefix = args.prefix.map(String::from);
let suffix = args.suffix.map(String::from);
{
- let cli_state = super::cli_state2(&state);
- cli_state.check_write(dir.clone().unwrap_or_else(temp_dir).as_path())?;
+ let state = state.borrow();
+ state
+ .borrow::<Permissions>()
+ .check_write(dir.clone().unwrap_or_else(temp_dir).as_path())?;
}
tokio::task::spawn_blocking(move || {
// TODO(piscisaureus): use byte vector for paths, not a string.
@@ -1525,8 +1559,9 @@ fn op_make_temp_file_sync(
let prefix = args.prefix.map(String::from);
let suffix = args.suffix.map(String::from);
- let cli_state = super::cli_state(state);
- cli_state.check_write(dir.clone().unwrap_or_else(temp_dir).as_path())?;
+ state
+ .borrow::<Permissions>()
+ .check_write(dir.clone().unwrap_or_else(temp_dir).as_path())?;
// TODO(piscisaureus): use byte vector for paths, not a string.
// See https://github.com/denoland/deno/issues/627.
@@ -1555,8 +1590,9 @@ async fn op_make_temp_file_async(
let suffix = args.suffix.map(String::from);
{
let state = state.borrow();
- let cli_state = super::cli_state(&state);
- cli_state.check_write(dir.clone().unwrap_or_else(temp_dir).as_path())?;
+ state
+ .borrow::<Permissions>()
+ .check_write(dir.clone().unwrap_or_else(temp_dir).as_path())?;
}
tokio::task::spawn_blocking(move || {
// TODO(piscisaureus): use byte vector for paths, not a string.
@@ -1591,7 +1627,7 @@ fn op_futime_sync(
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
{
- let cli_state = super::cli_state(state);
+ let cli_state = super::global_state(state);
cli_state.check_unstable("Deno.futimeSync");
}
let args: FutimeArgs = serde_json::from_value(args)?;
@@ -1618,7 +1654,7 @@ async fn op_futime_async(
_zero_copy: BufVec,
) -> Result<Value, AnyError> {
let mut state = state.borrow_mut();
- let cli_state = super::cli_state(&state);
+ let cli_state = super::global_state(&state);
cli_state.check_unstable("Deno.futime");
let args: FutimeArgs = serde_json::from_value(args)?;
let rid = args.rid as u32;
@@ -1651,7 +1687,7 @@ fn op_utime_sync(
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
- let cli_state = super::cli_state(state);
+ let cli_state = super::global_state(state);
cli_state.check_unstable("Deno.utime");
let args: UtimeArgs = serde_json::from_value(args)?;
@@ -1659,7 +1695,7 @@ fn op_utime_sync(
let atime = filetime::FileTime::from_unix_time(args.atime.0, args.atime.1);
let mtime = filetime::FileTime::from_unix_time(args.mtime.0, args.mtime.1);
- cli_state.check_write(&path)?;
+ state.borrow::<Permissions>().check_write(&path)?;
filetime::set_file_times(path, atime, mtime)?;
Ok(json!({}))
}
@@ -1670,7 +1706,7 @@ async fn op_utime_async(
_zero_copy: BufVec,
) -> Result<Value, AnyError> {
let state = state.borrow();
- let cli_state = super::cli_state(&state);
+ let cli_state = super::global_state(&state);
cli_state.check_unstable("Deno.utime");
let args: UtimeArgs = serde_json::from_value(args)?;
@@ -1678,7 +1714,7 @@ async fn op_utime_async(
let atime = filetime::FileTime::from_unix_time(args.atime.0, args.atime.1);
let mtime = filetime::FileTime::from_unix_time(args.mtime.0, args.mtime.1);
- cli_state.check_write(&path)?;
+ state.borrow::<Permissions>().check_write(&path)?;
tokio::task::spawn_blocking(move || {
filetime::set_file_times(path, atime, mtime)?;
@@ -1694,8 +1730,9 @@ fn op_cwd(
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
let path = current_dir()?;
- let cli_state = super::cli_state(state);
- cli_state.check_read_blind(&path, "CWD")?;
+ state
+ .borrow::<Permissions>()
+ .check_read_blind(&path, "CWD")?;
let path_str = into_string(path.into_os_string())?;
Ok(json!(path_str))
}
diff --git a/cli/ops/fs_events.rs b/cli/ops/fs_events.rs
index bba68f4e4..a79784c5a 100644
--- a/cli/ops/fs_events.rs
+++ b/cli/ops/fs_events.rs
@@ -1,5 +1,6 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
+use crate::permissions::Permissions;
use deno_core::error::bad_resource_id;
use deno_core::error::AnyError;
use deno_core::BufVec;
@@ -91,7 +92,9 @@ fn op_fs_events_open(
RecursiveMode::NonRecursive
};
for path in &args.paths {
- super::cli_state(state).check_read(&PathBuf::from(path))?;
+ state
+ .borrow::<Permissions>()
+ .check_read(&PathBuf::from(path))?;
watcher.watch(path, recursive_mode)?;
}
let resource = FsEventsResource { watcher, receiver };
diff --git a/cli/ops/mod.rs b/cli/ops/mod.rs
index 2c8e3472f..3149f147d 100644
--- a/cli/ops/mod.rs
+++ b/cli/ops/mod.rs
@@ -28,6 +28,7 @@ pub mod web_worker;
pub mod websocket;
pub mod worker_host;
+use crate::global_state::GlobalState;
use crate::metrics::metrics_op;
use deno_core::error::AnyError;
use deno_core::json_op_async;
@@ -40,6 +41,7 @@ use serde_json::Value;
use std::cell::RefCell;
use std::future::Future;
use std::rc::Rc;
+use std::sync::Arc;
pub fn reg_json_async<F, R>(rt: &mut JsRuntime, name: &'static str, op_fn: F)
where
@@ -58,12 +60,12 @@ where
}
/// Helper for extracting the commonly used state. Used for sync ops.
-pub fn cli_state(state: &OpState) -> Rc<crate::state::CliState> {
- state.borrow::<Rc<crate::state::CliState>>().clone()
+pub fn global_state(state: &OpState) -> Arc<GlobalState> {
+ state.borrow::<Arc<GlobalState>>().clone()
}
/// Helper for extracting the commonly used state. Used for async ops.
-pub fn cli_state2(state: &Rc<RefCell<OpState>>) -> Rc<crate::state::CliState> {
+pub fn global_state2(state: &Rc<RefCell<OpState>>) -> Arc<GlobalState> {
let state = state.borrow();
- state.borrow::<Rc<crate::state::CliState>>().clone()
+ state.borrow::<Arc<GlobalState>>().clone()
}
diff --git a/cli/ops/net.rs b/cli/ops/net.rs
index 44229f177..4e35f2247 100644
--- a/cli/ops/net.rs
+++ b/cli/ops/net.rs
@@ -2,6 +2,7 @@
use crate::ops::io::StreamResource;
use crate::ops::io::StreamResourceHolder;
+use crate::permissions::Permissions;
use crate::resolve_addr::resolve_addr;
use deno_core::error::bad_resource;
use deno_core::error::bad_resource_id;
@@ -189,7 +190,6 @@ async fn op_datagram_send(
) -> Result<Value, AnyError> {
assert_eq!(zero_copy.len(), 1, "Invalid number of arguments");
let zero_copy = zero_copy[0].clone();
- let cli_state = super::cli_state2(&state);
match serde_json::from_value(args)? {
SendArgs {
@@ -197,7 +197,11 @@ async fn op_datagram_send(
transport,
transport_args: ArgsEnum::Ip(args),
} if transport == "udp" => {
- cli_state.check_net(&args.hostname, args.port)?;
+ {
+ let s = state.borrow();
+ s.borrow::<Permissions>()
+ .check_net(&args.hostname, args.port)?;
+ }
let addr = resolve_addr(&args.hostname, args.port)?;
poll_fn(move |cx| {
let mut state = state.borrow_mut();
@@ -220,7 +224,10 @@ async fn op_datagram_send(
transport_args: ArgsEnum::Unix(args),
} if transport == "unixpacket" => {
let address_path = Path::new(&args.path);
- cli_state.check_read(&address_path)?;
+ {
+ let s = state.borrow();
+ s.borrow::<Permissions>().check_read(&address_path)?;
+ }
let mut state = state.borrow_mut();
let resource = state
.resource_table
@@ -251,13 +258,17 @@ async fn op_connect(
args: Value,
_zero_copy: BufVec,
) -> Result<Value, AnyError> {
- let cli_state = super::cli_state2(&state);
match serde_json::from_value(args)? {
ConnectArgs {
transport,
transport_args: ArgsEnum::Ip(args),
} if transport == "tcp" => {
- cli_state.check_net(&args.hostname, args.port)?;
+ {
+ let state_ = state.borrow();
+ state_
+ .borrow::<Permissions>()
+ .check_net(&args.hostname, args.port)?;
+ }
let addr = resolve_addr(&args.hostname, args.port)?;
let tcp_stream = TcpStream::connect(&addr).await?;
let local_addr = tcp_stream.local_addr()?;
@@ -290,8 +301,12 @@ async fn op_connect(
transport_args: ArgsEnum::Unix(args),
} if transport == "unix" => {
let address_path = Path::new(&args.path);
+ let cli_state = super::global_state2(&state);
cli_state.check_unstable("Deno.connect");
- cli_state.check_read(&address_path)?;
+ {
+ let state_ = state.borrow();
+ state_.borrow::<Permissions>().check_read(&address_path)?;
+ }
let path = args.path;
let unix_stream = net_unix::UnixStream::connect(Path::new(&path)).await?;
let local_addr = unix_stream.local_addr()?;
@@ -331,7 +346,7 @@ fn op_shutdown(
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
- super::cli_state(state).check_unstable("Deno.shutdown");
+ super::global_state(state).check_unstable("Deno.shutdown");
let args: ShutdownArgs = serde_json::from_value(args)?;
@@ -475,7 +490,8 @@ fn op_listen(
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
- let cli_state = super::cli_state(state);
+ let cli_state = super::global_state(state);
+ let permissions = state.borrow::<Permissions>();
match serde_json::from_value(args)? {
ListenArgs {
transport,
@@ -485,7 +501,7 @@ fn op_listen(
if transport == "udp" {
cli_state.check_unstable("Deno.listenDatagram");
}
- cli_state.check_net(&args.hostname, args.port)?;
+ permissions.check_net(&args.hostname, args.port)?;
}
let addr = resolve_addr(&args.hostname, args.port)?;
let (rid, local_addr) = if transport == "tcp" {
@@ -521,8 +537,8 @@ fn op_listen(
if transport == "unixpacket" {
cli_state.check_unstable("Deno.listenDatagram");
}
- cli_state.check_read(&address_path)?;
- cli_state.check_write(&address_path)?;
+ permissions.check_read(&address_path)?;
+ permissions.check_write(&address_path)?;
}
let (rid, local_addr) = if transport == "unix" {
net_unix::listen_unix(state, &address_path)?
diff --git a/cli/ops/os.rs b/cli/ops/os.rs
index d47d126ab..42d09da86 100644
--- a/cli/ops/os.rs
+++ b/cli/ops/os.rs
@@ -1,5 +1,6 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
+use crate::permissions::Permissions;
use deno_core::error::AnyError;
use deno_core::url::Url;
use deno_core::OpState;
@@ -28,8 +29,9 @@ fn op_exec_path(
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
let current_exe = env::current_exe().unwrap();
- let cli_state = super::cli_state(state);
- cli_state.check_read_blind(&current_exe, "exec_path")?;
+ state
+ .borrow::<Permissions>()
+ .check_read_blind(&current_exe, "exec_path")?;
// Now apply URL parser to current exe to get fully resolved path, otherwise
// we might get `./` and `../` bits in `exec_path`
let exe_url = Url::from_file_path(current_exe).unwrap();
@@ -49,8 +51,7 @@ fn op_set_env(
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
let args: SetEnv = serde_json::from_value(args)?;
- let cli_state = super::cli_state(state);
- cli_state.check_env()?;
+ state.borrow::<Permissions>().check_env()?;
env::set_var(args.key, args.value);
Ok(json!({}))
}
@@ -60,8 +61,7 @@ fn op_env(
_args: Value,
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
- let cli_state = super::cli_state(state);
- cli_state.check_env()?;
+ state.borrow::<Permissions>().check_env()?;
let v = env::vars().collect::<HashMap<String, String>>();
Ok(json!(v))
}
@@ -77,8 +77,7 @@ fn op_get_env(
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
let args: GetEnv = serde_json::from_value(args)?;
- let cli_state = super::cli_state(state);
- cli_state.check_env()?;
+ state.borrow::<Permissions>().check_env()?;
let r = match env::var(args.key) {
Err(env::VarError::NotPresent) => json!([]),
v => json!([v?]),
@@ -97,8 +96,7 @@ fn op_delete_env(
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
let args: DeleteEnv = serde_json::from_value(args)?;
- let cli_state = super::cli_state(state);
- cli_state.check_env()?;
+ state.borrow::<Permissions>().check_env()?;
env::remove_var(args.key);
Ok(json!({}))
}
@@ -122,9 +120,9 @@ fn op_loadavg(
_args: Value,
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
- let cli_state = super::cli_state(state);
+ let cli_state = super::global_state(state);
cli_state.check_unstable("Deno.loadavg");
- cli_state.check_env()?;
+ state.borrow::<Permissions>().check_env()?;
match sys_info::loadavg() {
Ok(loadavg) => Ok(json!([loadavg.one, loadavg.five, loadavg.fifteen])),
Err(_) => Ok(json!([0f64, 0f64, 0f64])),
@@ -136,9 +134,9 @@ fn op_hostname(
_args: Value,
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
- let cli_state = super::cli_state(state);
+ let cli_state = super::global_state(state);
cli_state.check_unstable("Deno.hostname");
- cli_state.check_env()?;
+ state.borrow::<Permissions>().check_env()?;
let hostname = sys_info::hostname().unwrap_or_else(|_| "".to_string());
Ok(json!(hostname))
}
@@ -148,9 +146,9 @@ fn op_os_release(
_args: Value,
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
- let cli_state = super::cli_state(state);
+ let cli_state = super::global_state(state);
cli_state.check_unstable("Deno.osRelease");
- cli_state.check_env()?;
+ state.borrow::<Permissions>().check_env()?;
let release = sys_info::os_release().unwrap_or_else(|_| "".to_string());
Ok(json!(release))
}
@@ -160,9 +158,9 @@ fn op_system_memory_info(
_args: Value,
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
- let cli_state = super::cli_state(state);
+ let cli_state = super::global_state(state);
cli_state.check_unstable("Deno.systemMemoryInfo");
- cli_state.check_env()?;
+ state.borrow::<Permissions>().check_env()?;
match sys_info::mem_info() {
Ok(info) => Ok(json!({
"total": info.total,
diff --git a/cli/ops/permissions.rs b/cli/ops/permissions.rs
index 2cdb03e31..54dda78bc 100644
--- a/cli/ops/permissions.rs
+++ b/cli/ops/permissions.rs
@@ -1,5 +1,6 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
+use crate::permissions::Permissions;
use deno_core::error::custom_error;
use deno_core::error::AnyError;
use deno_core::OpState;
@@ -27,8 +28,7 @@ pub fn op_query_permission(
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
let args: PermissionArgs = serde_json::from_value(args)?;
- let cli_state = super::cli_state(state);
- let permissions = cli_state.permissions.borrow();
+ let permissions = state.borrow::<Permissions>();
let path = args.path.as_deref();
let perm = match args.name.as_ref() {
"read" => permissions.query_read(&path.as_deref().map(Path::new)),
@@ -54,8 +54,7 @@ pub fn op_revoke_permission(
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
let args: PermissionArgs = serde_json::from_value(args)?;
- let cli_state = super::cli_state(state);
- let mut permissions = cli_state.permissions.borrow_mut();
+ let permissions = state.borrow_mut::<Permissions>();
let path = args.path.as_deref();
let perm = match args.name.as_ref() {
"read" => permissions.revoke_read(&path.as_deref().map(Path::new)),
@@ -81,8 +80,7 @@ pub fn op_request_permission(
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
let args: PermissionArgs = serde_json::from_value(args)?;
- let cli_state = super::cli_state(state);
- let permissions = &mut cli_state.permissions.borrow_mut();
+ let permissions = state.borrow_mut::<Permissions>();
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 e0081ce09..c862fb674 100644
--- a/cli/ops/plugin.rs
+++ b/cli/ops/plugin.rs
@@ -1,6 +1,7 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use crate::metrics::metrics_op;
+use crate::permissions::Permissions;
use deno_core::error::AnyError;
use deno_core::plugin_api;
use deno_core::BufVec;
@@ -39,9 +40,10 @@ pub fn op_open_plugin(
let args: OpenPluginArgs = serde_json::from_value(args)?;
let filename = PathBuf::from(&args.filename);
- let cli_state = super::cli_state(state);
+ let cli_state = super::global_state(state);
cli_state.check_unstable("Deno.openPlugin");
- cli_state.check_plugin(&filename)?;
+ let permissions = state.borrow::<Permissions>();
+ permissions.check_plugin(&filename)?;
debug!("Loading Plugin: {:#?}", filename);
let plugin_lib = Library::open(filename).map(Rc::new)?;
diff --git a/cli/ops/process.rs b/cli/ops/process.rs
index 3a7db8249..5099889cd 100644
--- a/cli/ops/process.rs
+++ b/cli/ops/process.rs
@@ -1,6 +1,7 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use super::io::{std_file_resource, StreamResource, StreamResourceHolder};
+use crate::permissions::Permissions;
use crate::signal::kill;
use deno_core::error::bad_resource_id;
use deno_core::error::type_error;
@@ -68,7 +69,7 @@ fn op_run(
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
let run_args: RunArgs = serde_json::from_value(args)?;
- super::cli_state(state).check_run()?;
+ state.borrow::<Permissions>().check_run()?;
let args = run_args.cmd;
let env = run_args.env;
@@ -178,7 +179,10 @@ async fn op_run_status(
let args: RunStatusArgs = serde_json::from_value(args)?;
let rid = args.rid as u32;
- super::cli_state2(&state).check_run()?;
+ {
+ let s = state.borrow();
+ s.borrow::<Permissions>().check_run()?;
+ }
let run_status = poll_fn(|cx| {
let mut state = state.borrow_mut();
@@ -221,9 +225,9 @@ fn op_kill(
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
- let cli_state = super::cli_state(state);
+ let cli_state = super::global_state(state);
cli_state.check_unstable("Deno.kill");
- cli_state.check_run()?;
+ state.borrow::<Permissions>().check_run()?;
let args: KillArgs = serde_json::from_value(args)?;
kill(args.pid, args.signo)?;
diff --git a/cli/ops/repl.rs b/cli/ops/repl.rs
index d2fe5ebe9..c87f7dc5c 100644
--- a/cli/ops/repl.rs
+++ b/cli/ops/repl.rs
@@ -35,8 +35,8 @@ fn op_repl_start(
let args: ReplStartArgs = serde_json::from_value(args)?;
debug!("op_repl_start {}", args.history_file);
let history_path = {
- let cli_state = super::cli_state(state);
- repl::history_path(&cli_state.global_state.dir, &args.history_file)
+ let cli_state = super::global_state(state);
+ repl::history_path(&cli_state.dir, &args.history_file)
};
let repl = repl::Repl::new(history_path);
let resource = ReplResource(Arc::new(Mutex::new(repl)));
diff --git a/cli/ops/runtime.rs b/cli/ops/runtime.rs
index 4c5775bcd..27f2dc8c5 100644
--- a/cli/ops/runtime.rs
+++ b/cli/ops/runtime.rs
@@ -2,6 +2,7 @@
use crate::colors;
use crate::metrics::Metrics;
+use crate::permissions::Permissions;
use crate::version;
use crate::DenoSubcommand;
use deno_core::error::AnyError;
@@ -22,7 +23,7 @@ fn op_start(
_args: Value,
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
- let gs = &super::cli_state(state).global_state;
+ let gs = &super::global_state(state);
Ok(json!({
// TODO(bartlomieju): `cwd` field is not used in JS, remove?
@@ -47,12 +48,13 @@ fn op_main_module(
_args: Value,
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
- let cli_state = super::cli_state(state);
- let main = &cli_state.main_module.to_string();
+ let main = state.borrow::<ModuleSpecifier>().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());
- cli_state.check_read_blind(&main_path, "main_module")?;
+ state
+ .borrow::<Permissions>()
+ .check_read_blind(&main_path, "main_module")?;
}
Ok(json!(&main))
}
diff --git a/cli/ops/runtime_compiler.rs b/cli/ops/runtime_compiler.rs
index 708a60cfa..f2839585c 100644
--- a/cli/ops/runtime_compiler.rs
+++ b/cli/ops/runtime_compiler.rs
@@ -1,5 +1,6 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
+use crate::permissions::Permissions;
use crate::tsc::runtime_bundle;
use crate::tsc::runtime_compile;
use crate::tsc::runtime_transpile;
@@ -32,11 +33,14 @@ async fn op_compile(
args: Value,
_data: BufVec,
) -> Result<Value, AnyError> {
- let cli_state = super::cli_state2(&state);
+ let cli_state = super::global_state2(&state);
cli_state.check_unstable("Deno.compile");
let args: CompileArgs = serde_json::from_value(args)?;
- let global_state = cli_state.global_state.clone();
- let permissions = cli_state.permissions.borrow().clone();
+ let global_state = cli_state.clone();
+ let permissions = {
+ let state = state.borrow();
+ state.borrow::<Permissions>().clone()
+ };
let fut = if args.bundle {
runtime_bundle(
&global_state,
@@ -71,11 +75,14 @@ async fn op_transpile(
args: Value,
_data: BufVec,
) -> Result<Value, AnyError> {
- let cli_state = super::cli_state2(&state);
+ let cli_state = super::global_state2(&state);
cli_state.check_unstable("Deno.transpile");
let args: TranspileArgs = serde_json::from_value(args)?;
- let global_state = cli_state.global_state.clone();
- let permissions = cli_state.permissions.borrow().clone();
+ let global_state = cli_state.clone();
+ let permissions = {
+ let state = state.borrow();
+ state.borrow::<Permissions>().clone()
+ };
let result =
runtime_transpile(&global_state, permissions, &args.sources, &args.options)
.await?;
diff --git a/cli/ops/signal.rs b/cli/ops/signal.rs
index a731a72aa..3f4c5c8ee 100644
--- a/cli/ops/signal.rs
+++ b/cli/ops/signal.rs
@@ -48,7 +48,7 @@ fn op_signal_bind(
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
- super::cli_state(state).check_unstable("Deno.signal");
+ super::global_state(state).check_unstable("Deno.signal");
let args: BindSignalArgs = serde_json::from_value(args)?;
let rid = state.resource_table.add(
"signal",
@@ -68,7 +68,7 @@ async fn op_signal_poll(
args: Value,
_zero_copy: BufVec,
) -> Result<Value, AnyError> {
- super::cli_state2(&state).check_unstable("Deno.signal");
+ super::global_state2(&state).check_unstable("Deno.signal");
let args: SignalArgs = serde_json::from_value(args)?;
let rid = args.rid as u32;
@@ -92,7 +92,7 @@ pub fn op_signal_unbind(
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
- super::cli_state(state).check_unstable("Deno.signal");
+ super::global_state(state).check_unstable("Deno.signal");
let args: SignalArgs = serde_json::from_value(args)?;
let rid = args.rid as u32;
let resource = state.resource_table.get_mut::<SignalStreamResource>(rid);
diff --git a/cli/ops/timers.rs b/cli/ops/timers.rs
index e52bb5b0e..a3aef3fef 100644
--- a/cli/ops/timers.rs
+++ b/cli/ops/timers.rs
@@ -1,17 +1,61 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
-use crate::global_timer::GlobalTimer;
+//! This module helps deno implement timers.
+//!
+//! As an optimization, we want to avoid an expensive calls into rust for every
+//! setTimeout in JavaScript. Thus in //js/timers.ts a data structure is
+//! implemented that calls into Rust for only the smallest timeout. Thus we
+//! only need to be able to start and cancel a single timer (or Delay, as Tokio
+//! calls it) for an entire Isolate. This is what is implemented here.
+
+use crate::permissions::Permissions;
use deno_core::error::AnyError;
use deno_core::BufVec;
use deno_core::OpState;
use deno_core::ZeroCopyBuf;
-use futures::future::FutureExt;
+use futures::channel::oneshot;
+use futures::FutureExt;
+use futures::TryFutureExt;
use serde::Deserialize;
use serde_json::Value;
use std::cell::RefCell;
+use std::future::Future;
use std::rc::Rc;
use std::time::Duration;
use std::time::Instant;
+pub type StartTime = Instant;
+
+#[derive(Default)]
+pub struct GlobalTimer {
+ tx: Option<oneshot::Sender<()>>,
+}
+
+impl GlobalTimer {
+ pub fn cancel(&mut self) {
+ if let Some(tx) = self.tx.take() {
+ tx.send(()).ok();
+ }
+ }
+
+ pub fn new_timeout(
+ &mut self,
+ deadline: Instant,
+ ) -> impl Future<Output = Result<(), ()>> {
+ if self.tx.is_some() {
+ self.cancel();
+ }
+ assert!(self.tx.is_none());
+
+ let (tx, rx) = oneshot::channel();
+ self.tx = Some(tx);
+
+ let delay = tokio::time::delay_until(deadline.into());
+ let rx = rx
+ .map_err(|err| panic!("Unexpected error in receiving channel {:?}", err));
+
+ futures::future::select(delay, rx).then(|_| futures::future::ok(()))
+ }
+}
pub fn init(rt: &mut deno_core::JsRuntime) {
super::reg_json_sync(rt, "op_global_timer_stop", op_global_timer_stop);
@@ -61,15 +105,15 @@ fn op_now(
_args: Value,
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
- let cli_state = super::cli_state(state);
- let seconds = cli_state.start_time.elapsed().as_secs();
- let mut subsec_nanos = cli_state.start_time.elapsed().subsec_nanos();
+ let start_time = state.borrow::<StartTime>();
+ let seconds = start_time.elapsed().as_secs();
+ let mut subsec_nanos = start_time.elapsed().subsec_nanos();
let reduced_time_precision = 2_000_000; // 2ms in nanoseconds
// If the permission is not enabled
// Round the nano result on 2 milliseconds
// see: https://developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp#Reduced_time_precision
- if cli_state.check_hrtime().is_err() {
+ if state.borrow::<Permissions>().check_hrtime().is_err() {
subsec_nanos -= subsec_nanos % reduced_time_precision;
}
diff --git a/cli/ops/tls.rs b/cli/ops/tls.rs
index 38b18077d..448e33a9d 100644
--- a/cli/ops/tls.rs
+++ b/cli/ops/tls.rs
@@ -1,6 +1,7 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use super::io::{StreamResource, StreamResourceHolder};
+use crate::permissions::Permissions;
use crate::resolve_addr::resolve_addr;
use deno_core::error::bad_resource;
use deno_core::error::bad_resource_id;
@@ -72,11 +73,13 @@ async fn op_start_tls(
domain.push_str("localhost");
}
{
- let cli_state = super::cli_state2(&state);
+ let cli_state = super::global_state2(&state);
cli_state.check_unstable("Deno.startTls");
- cli_state.check_net(&domain, 0)?;
+ let s = state.borrow();
+ let permissions = s.borrow::<Permissions>();
+ permissions.check_net(&domain, 0)?;
if let Some(path) = cert_file.clone() {
- cli_state.check_read(Path::new(&path))?;
+ permissions.check_read(Path::new(&path))?;
}
}
let mut resource_holder = {
@@ -143,10 +146,11 @@ async fn op_connect_tls(
let args: ConnectTLSArgs = serde_json::from_value(args)?;
let cert_file = args.cert_file.clone();
{
- let cli_state = super::cli_state2(&state);
- cli_state.check_net(&args.hostname, args.port)?;
+ let s = state.borrow();
+ let permissions = s.borrow::<Permissions>();
+ permissions.check_net(&args.hostname, args.port)?;
if let Some(path) = cert_file.clone() {
- cli_state.check_read(Path::new(&path))?;
+ permissions.check_read(Path::new(&path))?;
}
}
let mut domain = args.hostname.clone();
@@ -318,10 +322,10 @@ fn op_listen_tls(
let cert_file = args.cert_file;
let key_file = args.key_file;
{
- let cli_state = super::cli_state(state);
- cli_state.check_net(&args.hostname, args.port)?;
- cli_state.check_read(Path::new(&cert_file))?;
- cli_state.check_read(Path::new(&key_file))?;
+ let permissions = state.borrow::<Permissions>();
+ permissions.check_net(&args.hostname, args.port)?;
+ permissions.check_read(Path::new(&cert_file))?;
+ permissions.check_read(Path::new(&key_file))?;
}
let mut config = ServerConfig::new(NoClientAuth::new());
config
diff --git a/cli/ops/tty.rs b/cli/ops/tty.rs
index 54ebcada6..410256163 100644
--- a/cli/ops/tty.rs
+++ b/cli/ops/tty.rs
@@ -62,7 +62,7 @@ fn op_set_raw(
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
- super::cli_state(state).check_unstable("Deno.setRaw");
+ super::global_state(state).check_unstable("Deno.setRaw");
let args: SetRawArgs = serde_json::from_value(args)?;
let rid = args.rid;
@@ -273,7 +273,7 @@ fn op_console_size(
args: Value,
_zero_copy: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
- super::cli_state(state).check_unstable("Deno.consoleSize");
+ super::global_state(state).check_unstable("Deno.consoleSize");
let args: ConsoleSizeArgs = serde_json::from_value(args)?;
let rid = args.rid;
diff --git a/cli/ops/websocket.rs b/cli/ops/websocket.rs
index 5126b93c0..e16ce258c 100644
--- a/cli/ops/websocket.rs
+++ b/cli/ops/websocket.rs
@@ -1,5 +1,6 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
+use crate::permissions::Permissions;
use core::task::Poll;
use deno_core::error::bad_resource_id;
use deno_core::error::type_error;
@@ -55,10 +56,14 @@ pub async fn op_ws_create(
_bufs: BufVec,
) -> Result<Value, AnyError> {
let args: CreateArgs = serde_json::from_value(args)?;
+ {
+ let s = state.borrow();
+ s.borrow::<Permissions>()
+ .check_net_url(&url::Url::parse(&args.url)?)?;
+ }
let ca_file = {
- let cli_state = super::cli_state2(&state);
- cli_state.check_net_url(&url::Url::parse(&args.url)?)?;
- cli_state.global_state.flags.ca_file.clone()
+ let cli_state = super::global_state2(&state);
+ cli_state.flags.ca_file.clone()
};
let uri: Uri = args.url.parse()?;
let request = Request::builder()
diff --git a/cli/ops/worker_host.rs b/cli/ops/worker_host.rs
index deaf6a06b..f7b981c14 100644
--- a/cli/ops/worker_host.rs
+++ b/cli/ops/worker_host.rs
@@ -17,6 +17,7 @@ use futures::future::FutureExt;
use serde::Deserialize;
use serde_json::Value;
use std::cell::RefCell;
+use std::collections::HashMap;
use std::convert::From;
use std::rc::Rc;
use std::sync::Arc;
@@ -33,6 +34,9 @@ pub fn init(rt: &mut deno_core::JsRuntime) {
super::reg_json_async(rt, "op_host_get_message", op_host_get_message);
}
+pub type WorkersTable = HashMap<u32, (JoinHandle<()>, WebWorkerHandle)>;
+pub type WorkerId = u32;
+
fn create_web_worker(
worker_id: u32,
name: String,
@@ -41,13 +45,13 @@ fn create_web_worker(
specifier: ModuleSpecifier,
has_deno_namespace: bool,
) -> Result<WebWorker, AnyError> {
- let cli_state = crate::state::CliState::new_for_worker(
- global_state,
- Some(permissions),
+ let mut worker = WebWorker::new(
+ name.clone(),
+ permissions,
specifier,
- )?;
-
- let mut worker = WebWorker::new(name.clone(), &cli_state, has_deno_namespace);
+ global_state.clone(),
+ has_deno_namespace,
+ );
if has_deno_namespace {
let state = worker.isolate.op_state();
@@ -178,7 +182,7 @@ fn op_create_worker(
args: Value,
_data: &mut [ZeroCopyBuf],
) -> Result<Value, AnyError> {
- let cli_state = super::cli_state(state);
+ let cli_state = super::global_state(state);
let args: CreateWorkerArgs = serde_json::from_value(args)?;
let specifier = args.specifier.clone();
@@ -192,10 +196,9 @@ fn op_create_worker(
if use_deno_namespace {
cli_state.check_unstable("Worker.deno");
}
- let global_state = cli_state.global_state.clone();
- let permissions = cli_state.permissions.borrow().clone();
- let worker_id = cli_state.next_worker_id.get();
- cli_state.next_worker_id.set(worker_id + 1);
+ let permissions = state.borrow::<Permissions>().clone();
+ let worker_id = state.take::<WorkerId>();
+ state.put::<WorkerId>(worker_id + 1);
let module_specifier = ModuleSpecifier::resolve_url(&specifier)?;
let worker_name = args_name.unwrap_or_else(|| "".to_string());
@@ -203,7 +206,7 @@ fn op_create_worker(
let (join_handle, worker_handle) = run_worker_thread(
worker_id,
worker_name,
- &global_state,
+ &cli_state,
permissions,
module_specifier,
use_deno_namespace,
@@ -211,10 +214,8 @@ fn op_create_worker(
)?;
// At this point all interactions with worker happen using thread
// safe handler returned from previous function call
- let cli_state = super::cli_state(state);
- cli_state
- .workers
- .borrow_mut()
+ state
+ .borrow_mut::<WorkersTable>()
.insert(worker_id, (join_handle, worker_handle));
Ok(json!({ "id": worker_id }))
@@ -232,10 +233,8 @@ fn op_host_terminate_worker(
) -> Result<Value, AnyError> {
let args: WorkerArgs = serde_json::from_value(args)?;
let id = args.id as u32;
- let cli_state = super::cli_state(state);
- let (join_handle, worker_handle) = cli_state
- .workers
- .borrow_mut()
+ let (join_handle, worker_handle) = state
+ .borrow_mut::<WorkersTable>()
.remove(&id)
.expect("No worker handle found");
worker_handle.terminate();
@@ -301,10 +300,10 @@ async fn op_host_get_message(
) -> Result<Value, AnyError> {
let args: WorkerArgs = serde_json::from_value(args)?;
let id = args.id as u32;
- let cli_state = super::cli_state2(&state);
let worker_handle = {
- let workers_table = cli_state.workers.borrow();
+ let s = state.borrow();
+ let workers_table = s.borrow::<WorkersTable>();
let maybe_handle = workers_table.get(&id);
if let Some(handle) = maybe_handle {
handle.1.clone()
@@ -318,8 +317,9 @@ async fn op_host_get_message(
Some(event) => {
// Terminal error means that worker should be removed from worker table.
if let WorkerEvent::TerminalError(_) = &event {
+ let mut s = state.borrow_mut();
if let Some((join_handle, mut worker_handle)) =
- cli_state.workers.borrow_mut().remove(&id)
+ s.borrow_mut::<WorkersTable>().remove(&id)
{
worker_handle.sender.close_channel();
join_handle.join().expect("Worker thread panicked");
@@ -329,7 +329,8 @@ async fn op_host_get_message(
}
None => {
// Worker shuts down
- let mut workers = cli_state.workers.borrow_mut();
+ let mut s = state.borrow_mut();
+ let workers = s.borrow_mut::<WorkersTable>();
// 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)) = workers.remove(&id) {
@@ -354,8 +355,7 @@ fn op_host_post_message(
let msg = Vec::from(&*data[0]).into_boxed_slice();
debug!("post message to worker {}", id);
- let cli_state = super::cli_state(state);
- let workers = cli_state.workers.borrow();
+ let workers = state.borrow::<WorkersTable>();
let worker_handle = workers[&id].1.clone();
worker_handle.post_message(msg)?;
Ok(json!({}))
diff --git a/cli/permissions.rs b/cli/permissions.rs
index 1864e4f37..06a33096f 100644
--- a/cli/permissions.rs
+++ b/cli/permissions.rs
@@ -626,6 +626,16 @@ impl Permissions {
}
}
+impl deno_fetch::FetchPermissions for Permissions {
+ fn check_net_url(&self, url: &url::Url) -> Result<(), AnyError> {
+ Permissions::check_net_url(self, url)
+ }
+
+ fn check_read(&self, p: &PathBuf) -> Result<(), AnyError> {
+ Permissions::check_read(self, p)
+ }
+}
+
/// Shows the permission prompt and returns the answer according to the user input.
/// This loops until the user gives the proper input.
#[cfg(not(test))]
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)
- }
-}
diff --git a/cli/tsc.rs b/cli/tsc.rs
index 1e75b7041..c4102cc42 100644
--- a/cli/tsc.rs
+++ b/cli/tsc.rs
@@ -18,7 +18,7 @@ use crate::module_graph::ModuleGraphLoader;
use crate::ops;
use crate::permissions::Permissions;
use crate::source_maps::SourceMapGetter;
-use crate::state::CliState;
+use crate::state::CliModuleLoader;
use crate::tsc_config;
use crate::version;
use crate::worker::Worker;
@@ -48,7 +48,6 @@ use std::ops::DerefMut;
use std::path::Path;
use std::path::PathBuf;
use std::pin::Pin;
-use std::rc::Rc;
use std::str;
use std::sync::atomic::Ordering;
use std::sync::Arc;
@@ -132,9 +131,25 @@ pub struct CompilerWorker {
}
impl CompilerWorker {
- pub fn new(name: String, state: &Rc<CliState>) -> Self {
- let mut worker =
- Worker::new(name, Some(js::compiler_isolate_init()), state);
+ pub fn new(
+ name: String,
+ permissions: Permissions,
+ global_state: Arc<GlobalState>,
+ ) -> Self {
+ let main_module =
+ ModuleSpecifier::resolve_url_or_path("./$deno$compiler.ts").unwrap();
+ // TODO(bartlomieju): compiler worker shouldn't require any loader/state
+ let loader = CliModuleLoader::new(None);
+ let mut worker = Worker::new(
+ name,
+ Some(js::compiler_isolate_init()),
+ permissions,
+ main_module,
+ global_state,
+ loader,
+ false,
+ true,
+ );
let response = Arc::new(Mutex::new(None));
ops::runtime::init(&mut worker);
ops::errors::init(&mut worker);
@@ -215,17 +230,12 @@ fn create_compiler_worker(
global_state: &Arc<GlobalState>,
permissions: Permissions,
) -> CompilerWorker {
- let entry_point =
- ModuleSpecifier::resolve_url_or_path("./$deno$compiler.ts").unwrap();
- let worker_state =
- CliState::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.
global_state.compiler_starts.fetch_add(1, Ordering::SeqCst);
- let mut worker = CompilerWorker::new("TS".to_string(), &worker_state);
+ let mut worker =
+ CompilerWorker::new("TS".to_string(), permissions, global_state.clone());
worker
.execute("globalThis.bootstrapCompilerRuntime()")
.unwrap();
diff --git a/cli/web_worker.rs b/cli/web_worker.rs
index a4d0fe24c..75704d924 100644
--- a/cli/web_worker.rs
+++ b/cli/web_worker.rs
@@ -1,13 +1,15 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
-
+use crate::global_state::GlobalState;
use crate::js;
use crate::ops;
-use crate::state::CliState;
+use crate::permissions::Permissions;
+use crate::state::CliModuleLoader;
use crate::worker::Worker;
use crate::worker::WorkerEvent;
use crate::worker::WorkerHandle;
use deno_core::error::AnyError;
use deno_core::v8;
+use deno_core::ModuleSpecifier;
use futures::channel::mpsc;
use futures::future::FutureExt;
use futures::stream::StreamExt;
@@ -15,7 +17,6 @@ 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;
@@ -85,10 +86,22 @@ pub struct WebWorker {
impl WebWorker {
pub fn new(
name: String,
- state: &Rc<CliState>,
+ permissions: Permissions,
+ main_module: ModuleSpecifier,
+ global_state: Arc<GlobalState>,
has_deno_namespace: bool,
) -> Self {
- let mut worker = Worker::new(name, Some(js::deno_isolate_init()), &state);
+ let loader = CliModuleLoader::new_for_worker();
+ let mut worker = Worker::new(
+ name,
+ Some(js::deno_isolate_init()),
+ permissions,
+ main_module,
+ global_state,
+ loader,
+ false,
+ false,
+ );
let terminated = Arc::new(AtomicBool::new(false));
let isolate_handle = worker.isolate.thread_safe_handle();
@@ -252,13 +265,20 @@ impl Future for WebWorker {
#[cfg(test)]
mod tests {
use super::*;
- use crate::state::CliState;
use crate::tokio_util;
use crate::worker::WorkerEvent;
fn create_test_worker() -> WebWorker {
- let state = CliState::mock("./hello.js");
- let mut worker = WebWorker::new("TEST".to_string(), &state, false);
+ let main_module =
+ ModuleSpecifier::resolve_url_or_path("./hello.js").unwrap();
+ let global_state = GlobalState::mock(vec!["deno".to_string()], None);
+ let mut worker = WebWorker::new(
+ "TEST".to_string(),
+ Permissions::allow_all(),
+ main_module,
+ global_state,
+ false,
+ );
worker
.execute("bootstrap.workerRuntime(\"TEST\", false)")
.unwrap();
diff --git a/cli/worker.rs b/cli/worker.rs
index f575caddc..f87cd5cf1 100644
--- a/cli/worker.rs
+++ b/cli/worker.rs
@@ -2,13 +2,16 @@
use crate::fmt_errors::JsError;
use crate::global_state::GlobalState;
-use crate::global_timer::GlobalTimer;
use crate::inspector::DenoInspector;
use crate::js;
use crate::metrics::Metrics;
use crate::ops;
use crate::ops::io::get_stdio;
-use crate::state::CliState;
+use crate::ops::timers;
+use crate::ops::worker_host::WorkerId;
+use crate::ops::worker_host::WorkersTable;
+use crate::permissions::Permissions;
+use crate::state::CliModuleLoader;
use deno_core::error::AnyError;
use deno_core::url::Url;
use deno_core::JsRuntime;
@@ -98,23 +101,28 @@ pub struct Worker {
pub name: String,
pub isolate: JsRuntime,
pub inspector: Option<Box<DenoInspector>>,
- pub state: Rc<CliState>,
pub waker: AtomicWaker,
pub(crate) internal_channels: WorkerChannelsInternal,
external_channels: WorkerHandle,
+ should_break_on_first_statement: bool,
}
impl Worker {
+ #[allow(clippy::too_many_arguments)]
pub fn new(
name: String,
startup_snapshot: Option<Snapshot>,
- state: &Rc<CliState>,
+ permissions: Permissions,
+ main_module: ModuleSpecifier,
+ global_state: Arc<GlobalState>,
+ state: Rc<CliModuleLoader>,
+ is_main: bool,
+ is_internal: bool,
) -> Self {
- let global_state = state.global_state.clone();
let global_state_ = global_state.clone();
let mut isolate = JsRuntime::new(RuntimeOptions {
- module_loader: Some(state.clone()),
+ module_loader: Some(state),
startup_snapshot,
js_error_create_fn: Some(Box::new(move |core_js_error| {
JsError::create(core_js_error, &global_state_.ts_compiler)
@@ -125,40 +133,51 @@ impl Worker {
let op_state = isolate.op_state();
let mut op_state = op_state.borrow_mut();
op_state.get_error_class_fn = &crate::errors::get_error_class_name;
- op_state.put(state.clone());
let ca_file = global_state.flags.ca_file.as_deref();
let client = crate::http_util::create_http_client(ca_file).unwrap();
op_state.put(client);
- op_state.put(GlobalTimer::default());
+ op_state.put(timers::GlobalTimer::default());
+ op_state.put(timers::StartTime::now());
if let Some(seed) = global_state.flags.seed {
op_state.put(StdRng::seed_from_u64(seed));
}
op_state.put(Metrics::default());
+
+ op_state.put(WorkersTable::default());
+ op_state.put(WorkerId::default());
+
+ op_state.put(permissions);
+
+ op_state.put(main_module);
+ op_state.put(global_state.clone());
}
let inspector = {
- let global_state = &state.global_state;
global_state
.flags
.inspect
.or(global_state.flags.inspect_brk)
- .filter(|_| !state.is_internal)
+ .filter(|_| !is_internal)
.map(|inspector_host| DenoInspector::new(&mut isolate, inspector_host))
};
+ let should_break_on_first_statement = inspector.is_some()
+ && is_main
+ && global_state.flags.inspect_brk.is_some();
+
let (internal_channels, external_channels) = create_channels();
Self {
name,
isolate,
inspector,
- state: state.clone(),
waker: AtomicWaker::new(),
internal_channels,
external_channels,
+ should_break_on_first_statement,
}
}
@@ -218,10 +237,7 @@ impl Worker {
}
fn wait_for_inspector_session(&mut self) {
- let should_break_on_first_statement = self.inspector.is_some() && {
- self.state.is_main && self.state.global_state.flags.inspect_brk.is_some()
- };
- if should_break_on_first_statement {
+ if self.should_break_on_first_statement {
self
.inspector
.as_mut()
@@ -278,9 +294,21 @@ impl MainWorker {
fn new(
name: String,
startup_snapshot: Option<Snapshot>,
- state: &Rc<CliState>,
+ permissions: Permissions,
+ main_module: ModuleSpecifier,
+ global_state: Arc<GlobalState>,
) -> Self {
- let mut worker = Worker::new(name, startup_snapshot, state);
+ let loader = CliModuleLoader::new(global_state.maybe_import_map.clone());
+ let mut worker = Worker::new(
+ name,
+ startup_snapshot,
+ permissions,
+ main_module,
+ global_state,
+ loader,
+ true,
+ false,
+ );
{
ops::runtime::init(&mut worker);
ops::runtime_compiler::init(&mut worker);
@@ -317,17 +345,12 @@ impl MainWorker {
global_state: &Arc<GlobalState>,
main_module: ModuleSpecifier,
) -> Result<MainWorker, AnyError> {
- let state = CliState::new(
- &global_state,
- None,
- main_module,
- global_state.maybe_import_map.clone(),
- false,
- )?;
let mut worker = MainWorker::new(
"main".to_string(),
Some(js::deno_isolate_init()),
- &state,
+ global_state.permissions.clone(),
+ main_module,
+ global_state.clone(),
);
{
let op_state = worker.op_state();
@@ -380,11 +403,15 @@ mod tests {
let module_specifier =
ModuleSpecifier::resolve_url_or_path(&p.to_string_lossy()).unwrap();
let global_state = GlobalState::new(flags::Flags::default()).unwrap();
- let state =
- CliState::new(&global_state, None, module_specifier.clone(), None, false)
- .unwrap();
+ let global_state_ = global_state.clone();
tokio_util::run_basic(async {
- let mut worker = MainWorker::new("TEST".to_string(), None, &state);
+ let mut worker = MainWorker::new(
+ "TEST".to_string(),
+ None,
+ global_state.permissions.clone(),
+ module_specifier.clone(),
+ global_state_,
+ );
let result = worker.execute_module(&module_specifier).await;
if let Err(err) = result {
eprintln!("execute_mod err {:?}", err);
@@ -394,7 +421,7 @@ mod tests {
}
});
// Check that we didn't start the compiler.
- assert_eq!(state.global_state.compiler_starts.load(Ordering::SeqCst), 0);
+ assert_eq!(global_state.compiler_starts.load(Ordering::SeqCst), 0);
}
#[test]
@@ -406,11 +433,15 @@ mod tests {
let module_specifier =
ModuleSpecifier::resolve_url_or_path(&p.to_string_lossy()).unwrap();
let global_state = GlobalState::new(flags::Flags::default()).unwrap();
- let state =
- CliState::new(&global_state, None, module_specifier.clone(), None, false)
- .unwrap();
+ let global_state_ = global_state.clone();
tokio_util::run_basic(async {
- let mut worker = MainWorker::new("TEST".to_string(), None, &state);
+ let mut worker = MainWorker::new(
+ "TEST".to_string(),
+ None,
+ global_state_.permissions.clone(),
+ module_specifier.clone(),
+ global_state_,
+ );
let result = worker.execute_module(&module_specifier).await;
if let Err(err) = result {
eprintln!("execute_mod err {:?}", err);
@@ -421,7 +452,7 @@ mod tests {
});
// Check that we didn't start the compiler.
- assert_eq!(state.global_state.compiler_starts.load(Ordering::SeqCst), 0);
+ assert_eq!(global_state.compiler_starts.load(Ordering::SeqCst), 0);
}
#[tokio::test]
@@ -441,13 +472,12 @@ mod tests {
..flags::Flags::default()
};
let global_state = GlobalState::new(flags).unwrap();
- let state =
- CliState::new(&global_state, None, module_specifier.clone(), None, false)
- .unwrap();
let mut worker = MainWorker::new(
"TEST".to_string(),
Some(js::deno_isolate_init()),
- &state,
+ global_state.permissions.clone(),
+ module_specifier.clone(),
+ global_state.clone(),
);
worker.execute("bootstrap.mainRuntime()").unwrap();
let result = worker.execute_module(&module_specifier).await;
@@ -458,15 +488,19 @@ mod tests {
panic!("Future got unexpected error: {:?}", e);
}
// Check that we've only invoked the compiler once.
- assert_eq!(state.global_state.compiler_starts.load(Ordering::SeqCst), 1);
+ assert_eq!(global_state.compiler_starts.load(Ordering::SeqCst), 1);
}
fn create_test_worker() -> MainWorker {
- let state = CliState::mock("./hello.js");
+ let main_module =
+ ModuleSpecifier::resolve_url_or_path("./hello.js").unwrap();
+ let global_state = GlobalState::mock(vec!["deno".to_string()], None);
let mut worker = MainWorker::new(
"TEST".to_string(),
Some(js::deno_isolate_init()),
- &state,
+ Permissions::allow_all(),
+ main_module,
+ global_state,
);
worker.execute("bootstrap.mainRuntime()").unwrap();
worker