mirror of
https://github.com/denoland/deno
synced 2024-08-27 12:00:17 +00:00
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"
This commit is contained in:
parent
aaa5e6613a
commit
b657d743a2
|
@ -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>,
|
||||
|
|
|
@ -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(()))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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!({
|
||||
|
|
|
@ -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>,
|
||||
);
|
||||
}
|
||||
|
|
209
cli/ops/fs.rs
209
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(¤t_dir()?, "CWD")?;
|
||||
permissions.check_read_blind(¤t_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(¤t_dir()?, "CWD")?;
|
||||
{
|
||||
let state = state.borrow();
|
||||
let permissions = state.borrow::<Permissions>();
|
||||
permissions.check_read(&path)?;
|
||||
if path.is_relative() {
|
||||
permissions.check_read_blind(¤t_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))
|
||||
}
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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)?
|
||||
|
|
|
@ -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(¤t_exe, "exec_path")?;
|
||||
state
|
||||
.borrow::<Permissions>()
|
||||
.check_read_blind(¤t_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,
|
||||
|
|
|
@ -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)),
|
||||
|
|
|
@ -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)?;
|
||||
|
|
|
@ -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)?;
|
||||
|
|
|
@ -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)));
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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?;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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!({}))
|
||||
|
|
|
@ -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))]
|
||||
|
|
227
cli/state.rs
227
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)
|
||||
}
|
||||
}
|
||||
|
|
34
cli/tsc.rs
34
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();
|
||||
|
|
|
@ -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();
|
||||
|
|
118
cli/worker.rs
118
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
|
||||
|
|
|
@ -5,10 +5,12 @@ use rusty_v8 as v8;
|
|||
use crate::error::generic_error;
|
||||
use crate::error::AnyError;
|
||||
use crate::module_specifier::ModuleSpecifier;
|
||||
use crate::OpState;
|
||||
use futures::future::FutureExt;
|
||||
use futures::stream::FuturesUnordered;
|
||||
use futures::stream::Stream;
|
||||
use futures::stream::TryStreamExt;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
use std::future::Future;
|
||||
|
@ -74,6 +76,7 @@ pub trait ModuleLoader {
|
|||
/// dynamic imports altogether.
|
||||
fn load(
|
||||
&self,
|
||||
op_state: Rc<RefCell<OpState>>,
|
||||
module_specifier: &ModuleSpecifier,
|
||||
maybe_referrer: Option<ModuleSpecifier>,
|
||||
is_dyn_import: bool,
|
||||
|
@ -89,6 +92,7 @@ pub trait ModuleLoader {
|
|||
/// It's not required to implement this method.
|
||||
fn prepare_load(
|
||||
&self,
|
||||
_op_state: Rc<RefCell<OpState>>,
|
||||
_load_id: ModuleLoadId,
|
||||
_module_specifier: &ModuleSpecifier,
|
||||
_maybe_referrer: Option<String>,
|
||||
|
@ -114,6 +118,7 @@ impl ModuleLoader for NoopModuleLoader {
|
|||
|
||||
fn load(
|
||||
&self,
|
||||
_op_state: Rc<RefCell<OpState>>,
|
||||
_module_specifier: &ModuleSpecifier,
|
||||
_maybe_referrer: Option<ModuleSpecifier>,
|
||||
_is_dyn_import: bool,
|
||||
|
@ -140,6 +145,7 @@ pub enum LoadState {
|
|||
|
||||
/// This future is used to implement parallel async module loading.
|
||||
pub struct RecursiveModuleLoad {
|
||||
op_state: Rc<RefCell<OpState>>,
|
||||
kind: Kind,
|
||||
// TODO(bartlomieju): in future this value should
|
||||
// be randomized
|
||||
|
@ -154,16 +160,18 @@ pub struct RecursiveModuleLoad {
|
|||
impl RecursiveModuleLoad {
|
||||
/// Starts a new parallel load of the given URL of the main module.
|
||||
pub fn main(
|
||||
op_state: Rc<RefCell<OpState>>,
|
||||
specifier: &str,
|
||||
code: Option<String>,
|
||||
loader: Rc<dyn ModuleLoader>,
|
||||
) -> Self {
|
||||
let kind = Kind::Main;
|
||||
let state = LoadState::ResolveMain(specifier.to_owned(), code);
|
||||
Self::new(kind, state, loader)
|
||||
Self::new(op_state, kind, state, loader)
|
||||
}
|
||||
|
||||
pub fn dynamic_import(
|
||||
op_state: Rc<RefCell<OpState>>,
|
||||
specifier: &str,
|
||||
referrer: &str,
|
||||
loader: Rc<dyn ModuleLoader>,
|
||||
|
@ -171,17 +179,23 @@ impl RecursiveModuleLoad {
|
|||
let kind = Kind::DynamicImport;
|
||||
let state =
|
||||
LoadState::ResolveImport(specifier.to_owned(), referrer.to_owned());
|
||||
Self::new(kind, state, loader)
|
||||
Self::new(op_state, kind, state, loader)
|
||||
}
|
||||
|
||||
pub fn is_dynamic_import(&self) -> bool {
|
||||
self.kind != Kind::Main
|
||||
}
|
||||
|
||||
fn new(kind: Kind, state: LoadState, loader: Rc<dyn ModuleLoader>) -> Self {
|
||||
fn new(
|
||||
op_state: Rc<RefCell<OpState>>,
|
||||
kind: Kind,
|
||||
state: LoadState,
|
||||
loader: Rc<dyn ModuleLoader>,
|
||||
) -> Self {
|
||||
Self {
|
||||
id: NEXT_LOAD_ID.fetch_add(1, Ordering::SeqCst),
|
||||
root_module_id: None,
|
||||
op_state,
|
||||
kind,
|
||||
state,
|
||||
loader,
|
||||
|
@ -212,6 +226,7 @@ impl RecursiveModuleLoad {
|
|||
let prepare_result = self
|
||||
.loader
|
||||
.prepare_load(
|
||||
self.op_state.clone(),
|
||||
self.id,
|
||||
&module_specifier,
|
||||
maybe_referrer,
|
||||
|
@ -248,7 +263,12 @@ impl RecursiveModuleLoad {
|
|||
}
|
||||
_ => self
|
||||
.loader
|
||||
.load(&module_specifier, None, self.is_dynamic_import())
|
||||
.load(
|
||||
self.op_state.clone(),
|
||||
&module_specifier,
|
||||
None,
|
||||
self.is_dynamic_import(),
|
||||
)
|
||||
.boxed_local(),
|
||||
};
|
||||
|
||||
|
@ -264,10 +284,12 @@ impl RecursiveModuleLoad {
|
|||
referrer: ModuleSpecifier,
|
||||
) {
|
||||
if !self.is_pending.contains(&specifier) {
|
||||
let fut =
|
||||
self
|
||||
.loader
|
||||
.load(&specifier, Some(referrer), self.is_dynamic_import());
|
||||
let fut = self.loader.load(
|
||||
self.op_state.clone(),
|
||||
&specifier,
|
||||
Some(referrer),
|
||||
self.is_dynamic_import(),
|
||||
);
|
||||
self.pending.push(fut.boxed_local());
|
||||
self.is_pending.insert(specifier);
|
||||
}
|
||||
|
@ -577,6 +599,7 @@ mod tests {
|
|||
|
||||
fn load(
|
||||
&self,
|
||||
_op_state: Rc<RefCell<OpState>>,
|
||||
module_specifier: &ModuleSpecifier,
|
||||
_maybe_referrer: Option<ModuleSpecifier>,
|
||||
_is_dyn_import: bool,
|
||||
|
|
|
@ -624,6 +624,7 @@ impl JsRuntimeState {
|
|||
debug!("dyn_import specifier {} referrer {} ", specifier, referrer);
|
||||
|
||||
let load = RecursiveModuleLoad::dynamic_import(
|
||||
self.op_state.clone(),
|
||||
specifier,
|
||||
referrer,
|
||||
self.loader.clone(),
|
||||
|
@ -1207,7 +1208,12 @@ impl JsRuntime {
|
|||
state.loader.clone()
|
||||
};
|
||||
|
||||
let load = RecursiveModuleLoad::main(&specifier.to_string(), code, loader);
|
||||
let load = RecursiveModuleLoad::main(
|
||||
self.op_state(),
|
||||
&specifier.to_string(),
|
||||
code,
|
||||
loader,
|
||||
);
|
||||
let (_load_id, prepare_result) = load.prepare().await;
|
||||
|
||||
let mut load = prepare_result?;
|
||||
|
@ -1890,6 +1896,7 @@ pub mod tests {
|
|||
|
||||
fn load(
|
||||
&self,
|
||||
_op_state: Rc<RefCell<OpState>>,
|
||||
_module_specifier: &ModuleSpecifier,
|
||||
_maybe_referrer: Option<ModuleSpecifier>,
|
||||
_is_dyn_import: bool,
|
||||
|
@ -1999,6 +2006,7 @@ pub mod tests {
|
|||
|
||||
fn load(
|
||||
&self,
|
||||
_op_state: Rc<RefCell<OpState>>,
|
||||
_module_specifier: &ModuleSpecifier,
|
||||
_maybe_referrer: Option<ModuleSpecifier>,
|
||||
_is_dyn_import: bool,
|
||||
|
@ -2059,6 +2067,7 @@ pub mod tests {
|
|||
|
||||
fn load(
|
||||
&self,
|
||||
_op_state: Rc<RefCell<OpState>>,
|
||||
specifier: &ModuleSpecifier,
|
||||
_maybe_referrer: Option<ModuleSpecifier>,
|
||||
_is_dyn_import: bool,
|
||||
|
@ -2074,6 +2083,7 @@ pub mod tests {
|
|||
|
||||
fn prepare_load(
|
||||
&self,
|
||||
_op_state: Rc<RefCell<OpState>>,
|
||||
_load_id: ModuleLoadId,
|
||||
_module_specifier: &ModuleSpecifier,
|
||||
_maybe_referrer: Option<String>,
|
||||
|
@ -2179,6 +2189,7 @@ pub mod tests {
|
|||
|
||||
fn load(
|
||||
&self,
|
||||
_op_state: Rc<RefCell<OpState>>,
|
||||
_module_specifier: &ModuleSpecifier,
|
||||
_maybe_referrer: Option<ModuleSpecifier>,
|
||||
_is_dyn_import: bool,
|
||||
|
|
|
@ -114,9 +114,7 @@ where
|
|||
|
||||
{
|
||||
let state_ = state.borrow();
|
||||
// TODO(ry) The Rc below is a hack because we store Rc<CliState> in OpState.
|
||||
// Ideally it could be removed.
|
||||
let permissions = state_.borrow::<Rc<FP>>();
|
||||
let permissions = state_.borrow::<FP>();
|
||||
permissions.check_net_url(&url_)?;
|
||||
}
|
||||
|
||||
|
@ -221,9 +219,7 @@ where
|
|||
let args: CreateHttpClientOptions = serde_json::from_value(args)?;
|
||||
|
||||
if let Some(ca_file) = args.ca_file.clone() {
|
||||
// TODO(ry) The Rc below is a hack because we store Rc<CliState> in OpState.
|
||||
// Ideally it could be removed.
|
||||
let permissions = state.borrow::<Rc<FP>>();
|
||||
let permissions = state.borrow::<FP>();
|
||||
permissions.check_read(&PathBuf::from(ca_file))?;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue