summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ansi.rs70
-rw-r--r--src/cli.rs90
-rw-r--r--src/compiler.rs151
-rw-r--r--src/deno_dir.rs1369
-rw-r--r--src/errors.rs207
-rw-r--r--src/flags.rs291
-rw-r--r--src/fs.rs110
-rw-r--r--src/global_timer.rs49
-rw-r--r--src/http_body.rs112
-rw-r--r--src/http_util.rs166
-rw-r--r--src/isolate.rs236
-rw-r--r--src/isolate_state.rs110
-rw-r--r--src/js_errors.rs424
-rw-r--r--src/main.rs140
-rw-r--r--src/modules.rs204
-rw-r--r--src/msg.fbs524
-rw-r--r--src/msg.rs26
-rw-r--r--src/msg_util.rs127
-rw-r--r--src/ops.rs2020
-rw-r--r--src/permissions.rs343
-rw-r--r--src/repl.rs114
-rw-r--r--src/resolve_addr.rs156
-rw-r--r--src/resources.rs494
-rw-r--r--src/startup_data.rs57
-rw-r--r--src/tokio_util.rs118
-rw-r--r--src/tokio_write.rs62
-rw-r--r--src/version.rs6
-rw-r--r--src/workers.rs181
28 files changed, 0 insertions, 7957 deletions
diff --git a/src/ansi.rs b/src/ansi.rs
deleted file mode 100644
index 95b5e0694..000000000
--- a/src/ansi.rs
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-use ansi_term::Color::Fixed;
-use ansi_term::Color::Red;
-use ansi_term::Style;
-use regex::Regex;
-use std::env;
-use std::fmt;
-
-lazy_static! {
- // STRIP_ANSI_RE and strip_ansi_codes are lifted from the "console" crate.
- // Copyright 2017 Armin Ronacher <armin.ronacher@active-4.com>. MIT License.
- static ref STRIP_ANSI_RE: Regex = Regex::new(
- r"[\x1b\x9b][\[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-PRZcf-nqry=><]"
- ).unwrap();
- static ref NO_COLOR: bool = {
- env::var_os("NO_COLOR").is_some()
- };
-}
-
-/// Helper function to strip ansi codes.
-#[cfg(test)]
-pub fn strip_ansi_codes(s: &str) -> std::borrow::Cow<str> {
- STRIP_ANSI_RE.replace_all(s, "")
-}
-
-pub fn use_color() -> bool {
- !(*NO_COLOR)
-}
-
-pub fn red_bold(s: String) -> impl fmt::Display {
- let mut style = Style::new();
- if use_color() {
- style = style.bold().fg(Red);
- }
- style.paint(s)
-}
-
-pub fn italic_bold(s: String) -> impl fmt::Display {
- let mut style = Style::new();
- if use_color() {
- style = style.italic().bold();
- }
- style.paint(s)
-}
-
-pub fn yellow(s: String) -> impl fmt::Display {
- let mut style = Style::new();
- if use_color() {
- // matches TypeScript's ForegroundColorEscapeSequences.Yellow
- style = style.fg(Fixed(11));
- }
- style.paint(s)
-}
-
-pub fn cyan(s: String) -> impl fmt::Display {
- let mut style = Style::new();
- if use_color() {
- // matches TypeScript's ForegroundColorEscapeSequences.Cyan
- style = style.fg(Fixed(14));
- }
- style.paint(s)
-}
-
-pub fn bold(s: String) -> impl fmt::Display {
- let mut style = Style::new();
- if use_color() {
- style = style.bold();
- }
- style.paint(s)
-}
diff --git a/src/cli.rs b/src/cli.rs
deleted file mode 100644
index 42b2b29f8..000000000
--- a/src/cli.rs
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-#![allow(unused_variables)]
-#![allow(dead_code)]
-
-use crate::errors::DenoResult;
-use crate::isolate_state::IsolateState;
-use crate::ops;
-use crate::permissions::DenoPermissions;
-use deno_core::deno_buf;
-use deno_core::deno_mod;
-use deno_core::Behavior;
-use deno_core::Op;
-use deno_core::StartupData;
-use std::sync::atomic::Ordering;
-use std::sync::Arc;
-
-// Buf represents a byte array returned from a "Op". The message might be empty
-// (which will be translated into a null object on the javascript side) or it is
-// a heap allocated opaque sequence of bytes. Usually a flatbuffer message.
-pub type Buf = Box<[u8]>;
-
-/// Implements deno_core::Behavior for the main Deno command-line.
-pub struct Cli {
- startup_data: Option<StartupData>,
- pub state: Arc<IsolateState>,
- pub permissions: Arc<DenoPermissions>, // TODO(ry) move to IsolateState
-}
-
-impl Cli {
- pub fn new(
- startup_data: Option<StartupData>,
- state: Arc<IsolateState>,
- permissions: DenoPermissions,
- ) -> Self {
- Self {
- startup_data,
- state,
- permissions: Arc::new(permissions),
- }
- }
-
- #[inline]
- pub fn check_read(&self, filename: &str) -> DenoResult<()> {
- self.permissions.check_read(filename)
- }
-
- #[inline]
- pub fn check_write(&self, filename: &str) -> DenoResult<()> {
- self.permissions.check_write(filename)
- }
-
- #[inline]
- pub fn check_env(&self) -> DenoResult<()> {
- self.permissions.check_env()
- }
-
- #[inline]
- pub fn check_net(&self, filename: &str) -> DenoResult<()> {
- self.permissions.check_net(filename)
- }
-
- #[inline]
- pub fn check_run(&self) -> DenoResult<()> {
- self.permissions.check_run()
- }
-}
-
-impl Behavior for Cli {
- fn startup_data(&mut self) -> Option<StartupData> {
- self.startup_data.take()
- }
-
- fn resolve(&mut self, specifier: &str, referrer: deno_mod) -> deno_mod {
- self
- .state
- .metrics
- .resolve_count
- .fetch_add(1, Ordering::Relaxed);
- let mut modules = self.state.modules.lock().unwrap();
- modules.resolve_cb(&self.state.dir, specifier, referrer)
- }
-
- fn dispatch(
- &mut self,
- control: &[u8],
- zero_copy: deno_buf,
- ) -> (bool, Box<Op>) {
- ops::dispatch(self, control, zero_copy)
- }
-}
diff --git a/src/compiler.rs b/src/compiler.rs
deleted file mode 100644
index 2d6e4a4b7..000000000
--- a/src/compiler.rs
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-use crate::cli::Buf;
-use crate::isolate_state::IsolateState;
-use crate::msg;
-use crate::permissions::{DenoPermissions, PermissionAccessor};
-use crate::resources;
-use crate::resources::Resource;
-use crate::resources::ResourceId;
-use crate::startup_data;
-use crate::workers;
-use futures::Future;
-use serde_json;
-use std::str;
-use std::sync::Mutex;
-
-lazy_static! {
- static ref C_RID: Mutex<Option<ResourceId>> = Mutex::new(None);
-}
-
-// This corresponds to JS ModuleMetaData.
-// TODO Rename one or the other so they correspond.
-#[derive(Debug)]
-pub struct ModuleMetaData {
- pub module_name: String,
- pub filename: String,
- pub media_type: msg::MediaType,
- pub source_code: Vec<u8>,
- pub maybe_output_code_filename: Option<String>,
- pub maybe_output_code: Option<Vec<u8>>,
- pub maybe_source_map_filename: Option<String>,
- pub maybe_source_map: Option<Vec<u8>>,
-}
-
-impl ModuleMetaData {
- pub fn js_source(&self) -> String {
- if self.media_type == msg::MediaType::Json {
- return format!(
- "export default {};",
- str::from_utf8(&self.source_code).unwrap()
- );
- }
- match self.maybe_output_code {
- None => str::from_utf8(&self.source_code).unwrap().to_string(),
- Some(ref output_code) => str::from_utf8(output_code).unwrap().to_string(),
- }
- }
-}
-
-fn lazy_start(parent_state: &IsolateState) -> Resource {
- let mut cell = C_RID.lock().unwrap();
- let startup_data = startup_data::compiler_isolate_init();
- let permissions = DenoPermissions {
- allow_read: PermissionAccessor::from(true),
- allow_write: PermissionAccessor::from(true),
- allow_net: PermissionAccessor::from(true),
- ..Default::default()
- };
-
- let rid = cell.get_or_insert_with(|| {
- let resource = workers::spawn(
- Some(startup_data),
- parent_state,
- "compilerMain()".to_string(),
- permissions,
- );
- resource.rid
- });
- Resource { rid: *rid }
-}
-
-fn req(specifier: &str, referrer: &str) -> Buf {
- json!({
- "specifier": specifier,
- "referrer": referrer,
- }).to_string()
- .into_boxed_str()
- .into_boxed_bytes()
-}
-
-pub fn compile_sync(
- parent_state: &IsolateState,
- specifier: &str,
- referrer: &str,
- module_meta_data: &ModuleMetaData,
-) -> ModuleMetaData {
- let req_msg = req(specifier, referrer);
-
- let compiler = lazy_start(parent_state);
-
- let send_future = resources::worker_post_message(compiler.rid, req_msg);
- send_future.wait().unwrap();
-
- let recv_future = resources::worker_recv_message(compiler.rid);
- let result = recv_future.wait().unwrap();
- assert!(result.is_some());
- let res_msg = result.unwrap();
-
- let res_json = std::str::from_utf8(&res_msg).unwrap();
- match serde_json::from_str::<serde_json::Value>(res_json) {
- Ok(serde_json::Value::Object(map)) => ModuleMetaData {
- module_name: module_meta_data.module_name.clone(),
- filename: module_meta_data.filename.clone(),
- media_type: module_meta_data.media_type,
- source_code: module_meta_data.source_code.clone(),
- maybe_output_code: match map["outputCode"].as_str() {
- Some(str) => Some(str.as_bytes().to_owned()),
- _ => None,
- },
- maybe_output_code_filename: None,
- maybe_source_map: match map["sourceMap"].as_str() {
- Some(str) => Some(str.as_bytes().to_owned()),
- _ => None,
- },
- maybe_source_map_filename: None,
- },
- _ => panic!("error decoding compiler response"),
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn test_compile_sync() {
- let cwd = std::env::current_dir().unwrap();
- let cwd_string = cwd.to_str().unwrap().to_owned();
-
- let specifier = "./tests/002_hello.ts";
- let referrer = cwd_string + "/";
-
- let mut out = ModuleMetaData {
- module_name: "xxx".to_owned(),
- filename: "/tests/002_hello.ts".to_owned(),
- media_type: msg::MediaType::TypeScript,
- source_code: "console.log(\"Hello World\");".as_bytes().to_owned(),
- maybe_output_code_filename: None,
- maybe_output_code: None,
- maybe_source_map_filename: None,
- maybe_source_map: None,
- };
-
- out = compile_sync(&IsolateState::mock(), specifier, &referrer, &mut out);
- assert!(
- out
- .maybe_output_code
- .unwrap()
- .starts_with("console.log(\"Hello World\");".as_bytes())
- );
- }
-}
diff --git a/src/deno_dir.rs b/src/deno_dir.rs
deleted file mode 100644
index 829af5aa2..000000000
--- a/src/deno_dir.rs
+++ /dev/null
@@ -1,1369 +0,0 @@
-// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-use crate::compiler::ModuleMetaData;
-use crate::errors;
-use crate::errors::DenoError;
-use crate::errors::DenoResult;
-use crate::errors::ErrorKind;
-use crate::fs as deno_fs;
-use crate::http_util;
-use crate::js_errors::SourceMapGetter;
-use crate::msg;
-use crate::version;
-
-use dirs;
-use ring;
-use std;
-use std::fmt::Write;
-use std::fs;
-use std::path::Path;
-use std::path::PathBuf;
-use std::result::Result;
-use std::str;
-use url;
-use url::Url;
-
-/// Gets corresponding MediaType given extension
-fn extmap(ext: &str) -> msg::MediaType {
- match ext {
- "ts" => msg::MediaType::TypeScript,
- "js" => msg::MediaType::JavaScript,
- "json" => msg::MediaType::Json,
- _ => msg::MediaType::Unknown,
- }
-}
-
-pub struct DenoDir {
- // Example: /Users/rld/.deno/
- pub root: PathBuf,
- // In the Go code this was called SrcDir.
- // This is where we cache http resources. Example:
- // /Users/rld/.deno/deps/github.com/ry/blah.js
- pub gen: PathBuf,
- // In the Go code this was called CacheDir.
- // This is where we cache compilation outputs. Example:
- // /Users/rld/.deno/gen/f39a473452321cacd7c346a870efb0e3e1264b43.js
- pub deps: PathBuf,
- // This splits to http and https deps
- pub deps_http: PathBuf,
- pub deps_https: PathBuf,
- // If remote resources should be reloaded.
- reload: bool,
- // recompile the typescript files.
- // if true, not load cache files
- // else, load cache files
- recompile: bool,
-}
-
-impl DenoDir {
- // Must be called before using any function from this module.
- // https://github.com/denoland/deno/blob/golang/deno_dir.go#L99-L111
- pub fn new(
- reload: bool,
- recompile: bool,
- custom_root: Option<PathBuf>,
- ) -> std::io::Result<Self> {
- // Only setup once.
- let home_dir = dirs::home_dir().expect("Could not get home directory.");
- let fallback = home_dir.join(".deno");
- // We use the OS cache dir because all files deno writes are cache files
- // Once that changes we need to start using different roots if DENO_DIR
- // is not set, and keep a single one if it is.
- let default = dirs::cache_dir()
- .map(|d| d.join("deno"))
- .unwrap_or(fallback);
-
- let root: PathBuf = custom_root.unwrap_or(default);
- let gen = root.as_path().join("gen");
- let deps = root.as_path().join("deps");
- let deps_http = deps.join("http");
- let deps_https = deps.join("https");
-
- let deno_dir = Self {
- root,
- gen,
- deps,
- deps_http,
- deps_https,
- reload,
- recompile,
- };
-
- // TODO Lazily create these directories.
- deno_fs::mkdir(deno_dir.gen.as_ref(), 0o755, true)?;
- deno_fs::mkdir(deno_dir.deps.as_ref(), 0o755, true)?;
- deno_fs::mkdir(deno_dir.deps_http.as_ref(), 0o755, true)?;
- deno_fs::mkdir(deno_dir.deps_https.as_ref(), 0o755, true)?;
-
- debug!("root {}", deno_dir.root.display());
- debug!("gen {}", deno_dir.gen.display());
- debug!("deps {}", deno_dir.deps.display());
- debug!("deps_http {}", deno_dir.deps_http.display());
- debug!("deps_https {}", deno_dir.deps_https.display());
-
- Ok(deno_dir)
- }
-
- // https://github.com/denoland/deno/blob/golang/deno_dir.go#L32-L35
- pub fn cache_path(
- self: &Self,
- filename: &str,
- source_code: &[u8],
- ) -> (PathBuf, PathBuf) {
- let cache_key = source_code_hash(filename, source_code, version::DENO);
- (
- self.gen.join(cache_key.to_string() + ".js"),
- self.gen.join(cache_key.to_string() + ".js.map"),
- )
- }
-
- fn load_cache(
- self: &Self,
- filename: &str,
- source_code: &[u8],
- ) -> Result<(Vec<u8>, Vec<u8>), std::io::Error> {
- let (output_code, source_map) = self.cache_path(filename, source_code);
- debug!(
- "load_cache code: {} map: {}",
- output_code.display(),
- source_map.display()
- );
- let read_output_code = fs::read(&output_code)?;
- let read_source_map = fs::read(&source_map)?;
- Ok((read_output_code, read_source_map))
- }
-
- pub fn code_cache(
- self: &Self,
- module_meta_data: &ModuleMetaData,
- ) -> std::io::Result<()> {
- let (cache_path, source_map_path) = self
- .cache_path(&module_meta_data.filename, &module_meta_data.source_code);
- // TODO(ry) This is a race condition w.r.t to exists() -- probably should
- // create the file in exclusive mode. A worry is what might happen is there
- // are two processes and one reads the cache file while the other is in the
- // midst of writing it.
- if cache_path.exists() && source_map_path.exists() {
- Ok(())
- } else {
- match &module_meta_data.maybe_output_code {
- Some(output_code) => fs::write(cache_path, output_code),
- _ => Ok(()),
- }?;
- match &module_meta_data.maybe_source_map {
- Some(source_map) => fs::write(source_map_path, source_map),
- _ => Ok(()),
- }?;
- Ok(())
- }
- }
-
- // Prototype https://github.com/denoland/deno/blob/golang/deno_dir.go#L37-L73
- /// Fetch remote source code.
- fn fetch_remote_source(
- self: &Self,
- module_name: &str,
- filename: &str,
- ) -> DenoResult<Option<ModuleMetaData>> {
- let p = Path::new(&filename);
- // We write a special ".mime" file into the `.deno/deps` directory along side the
- // cached file, containing just the media type.
- let media_type_filename = [&filename, ".mime"].concat();
- let mt = Path::new(&media_type_filename);
- eprint!("Downloading {}...", &module_name); // no newline
- let maybe_source = http_util::fetch_sync_string(&module_name);
- if let Ok((source, content_type)) = maybe_source {
- eprintln!(""); // next line
- match p.parent() {
- Some(ref parent) => fs::create_dir_all(parent),
- None => Ok(()),
- }?;
- deno_fs::write_file(&p, &source, 0o666)?;
- // Remove possibly existing stale .mime file
- // may not exist. DON'T unwrap
- let _ = std::fs::remove_file(&media_type_filename);
- // Create .mime file only when content type different from extension
- let resolved_content_type = map_content_type(&p, Some(&content_type));
- let ext = p
- .extension()
- .map(|x| x.to_str().unwrap_or(""))
- .unwrap_or("");
- let media_type = extmap(&ext);
- if media_type == msg::MediaType::Unknown
- || media_type != resolved_content_type
- {
- deno_fs::write_file(&mt, content_type.as_bytes(), 0o666)?
- }
- return Ok(Some(ModuleMetaData {
- module_name: module_name.to_string(),
- filename: filename.to_string(),
- media_type: map_content_type(&p, Some(&content_type)),
- source_code: source.as_bytes().to_owned(),
- maybe_output_code_filename: None,
- maybe_output_code: None,
- maybe_source_map_filename: None,
- maybe_source_map: None,
- }));
- } else {
- eprintln!(" NOT FOUND");
- }
- Ok(None)
- }
-
- /// Fetch local or cached source code.
- fn fetch_local_source(
- self: &Self,
- module_name: &str,
- filename: &str,
- ) -> DenoResult<Option<ModuleMetaData>> {
- let p = Path::new(&filename);
- let media_type_filename = [&filename, ".mime"].concat();
- let mt = Path::new(&media_type_filename);
- let source_code = match fs::read(p) {
- Err(e) => {
- if e.kind() == std::io::ErrorKind::NotFound {
- return Ok(None);
- } else {
- return Err(e.into());
- }
- }
- Ok(c) => c,
- };
- // .mime file might not exists
- // this is okay for local source: maybe_content_type_str will be None
- let maybe_content_type_string = fs::read_to_string(&mt).ok();
- // Option<String> -> Option<&str>
- let maybe_content_type_str =
- maybe_content_type_string.as_ref().map(String::as_str);
- Ok(Some(ModuleMetaData {
- module_name: module_name.to_string(),
- filename: filename.to_string(),
- media_type: map_content_type(&p, maybe_content_type_str),
- source_code,
- maybe_output_code_filename: None,
- maybe_output_code: None,
- maybe_source_map_filename: None,
- maybe_source_map: None,
- }))
- }
-
- // Prototype: https://github.com/denoland/deno/blob/golang/os.go#L122-L138
- fn get_source_code(
- self: &Self,
- module_name: &str,
- filename: &str,
- ) -> DenoResult<ModuleMetaData> {
- let is_module_remote = is_remote(module_name);
- // We try fetch local. Two cases:
- // 1. This is a remote module, but no reload provided
- // 2. This is a local module
- if !is_module_remote || !self.reload {
- debug!(
- "fetch local or reload {} is_module_remote {}",
- module_name, is_module_remote
- );
- match self.fetch_local_source(&module_name, &filename)? {
- Some(output) => {
- debug!("found local source ");
- return Ok(output);
- }
- None => {
- debug!("fetch_local_source returned None");
- }
- }
- }
-
- // If not remote file, stop here!
- if !is_module_remote {
- debug!("not remote file stop here");
- return Err(DenoError::from(std::io::Error::new(
- std::io::ErrorKind::NotFound,
- format!("cannot find local file '{}'", filename),
- )));
- }
-
- debug!("is remote but didn't find module");
-
- // not cached/local, try remote
- let maybe_remote_source =
- self.fetch_remote_source(&module_name, &filename)?;
- if let Some(output) = maybe_remote_source {
- return Ok(output);
- }
- Err(DenoError::from(std::io::Error::new(
- std::io::ErrorKind::NotFound,
- format!("cannot find remote file '{}'", filename),
- )))
- }
-
- pub fn fetch_module_meta_data(
- self: &Self,
- specifier: &str,
- referrer: &str,
- ) -> Result<ModuleMetaData, errors::DenoError> {
- debug!(
- "fetch_module_meta_data. specifier {} referrer {}",
- specifier, referrer
- );
-
- let (module_name, filename) = self.resolve_module(specifier, referrer)?;
-
- let result = self.get_source_code(module_name.as_str(), filename.as_str());
- let mut out = match result {
- Ok(out) => out,
- Err(err) => {
- if err.kind() == ErrorKind::NotFound {
- // For NotFound, change the message to something better.
- return Err(errors::new(
- ErrorKind::NotFound,
- format!(
- "Cannot resolve module \"{}\" from \"{}\"",
- specifier, referrer
- ),
- ));
- } else {
- return Err(err);
- }
- }
- };
-
- if out.source_code.starts_with("#!".as_bytes()) {
- out.source_code = filter_shebang(out.source_code);
- }
-
- if out.media_type != msg::MediaType::TypeScript {
- return Ok(out);
- }
-
- let (output_code_filename, output_source_map_filename) =
- self.cache_path(&out.filename, &out.source_code);
- let mut maybe_output_code = None;
- let mut maybe_source_map = None;
-
- if !self.recompile {
- let result = self.load_cache(out.filename.as_str(), &out.source_code);
- match result {
- Err(err) => {
- if err.kind() == std::io::ErrorKind::NotFound {
- return Ok(out);
- } else {
- return Err(err.into());
- }
- }
- Ok((output_code, source_map)) => {
- maybe_output_code = Some(output_code);
- maybe_source_map = Some(source_map);
- }
- }
- }
-
- Ok(ModuleMetaData {
- module_name: out.module_name,
- filename: out.filename,
- media_type: out.media_type,
- source_code: out.source_code,
- maybe_output_code_filename: output_code_filename
- .to_str()
- .map(String::from),
- maybe_output_code,
- maybe_source_map_filename: output_source_map_filename
- .to_str()
- .map(String::from),
- maybe_source_map,
- })
- }
-
- // Prototype: https://github.com/denoland/deno/blob/golang/os.go#L56-L68
- fn src_file_to_url(self: &Self, filename: &str) -> String {
- let filename_path = Path::new(filename);
- if filename_path.starts_with(&self.deps) {
- let (rest, prefix) = if filename_path.starts_with(&self.deps_https) {
- let rest = filename_path.strip_prefix(&self.deps_https).unwrap();
- let prefix = "https://".to_string();
- (rest, prefix)
- } else if filename_path.starts_with(&self.deps_http) {
- let rest = filename_path.strip_prefix(&self.deps_http).unwrap();
- let prefix = "http://".to_string();
- (rest, prefix)
- } else {
- // TODO(kevinkassimo): change this to support other protocols than http
- unimplemented!()
- };
- // Windows doesn't support ":" in filenames, so we represent port using a
- // special string.
- // TODO(ry) This current implementation will break on a URL that has
- // the default port but contains "_PORT" in the path.
- let rest = rest.to_str().unwrap().replacen("_PORT", ":", 1);
- prefix + &rest
- } else {
- String::from(filename)
- }
- }
-
- /// Returns (module name, local filename)
- pub fn resolve_module_url(
- self: &Self,
- specifier: &str,
- referrer: &str,
- ) -> Result<Url, url::ParseError> {
- let specifier = self.src_file_to_url(specifier);
- let mut referrer = self.src_file_to_url(referrer);
-
- debug!(
- "resolve_module specifier {} referrer {}",
- specifier, referrer
- );
-
- if referrer.starts_with('.') {
- let cwd = std::env::current_dir().unwrap();
- let referrer_path = cwd.join(referrer);
- referrer = referrer_path.to_str().unwrap().to_string() + "/";
- }
-
- let j = if is_remote(&specifier) || Path::new(&specifier).is_absolute() {
- parse_local_or_remote(&specifier)?
- } else if referrer.ends_with('/') {
- let r = Url::from_directory_path(&referrer);
- // TODO(ry) Properly handle error.
- if r.is_err() {
- error!("Url::from_directory_path error {}", referrer);
- }
- let base = r.unwrap();
- base.join(specifier.as_ref())?
- } else {
- let base = parse_local_or_remote(&referrer)?;
- base.join(specifier.as_ref())?
- };
- Ok(j)
- }
-
- /// Returns (module name, local filename)
- pub fn resolve_module(
- self: &Self,
- specifier: &str,
- referrer: &str,
- ) -> Result<(String, String), url::ParseError> {
- let j = self.resolve_module_url(specifier, referrer)?;
-
- let module_name = j.to_string();
- let filename;
- match j.scheme() {
- "file" => {
- filename = deno_fs::normalize_path(j.to_file_path().unwrap().as_ref());
- }
- "https" => {
- filename = deno_fs::normalize_path(
- get_cache_filename(self.deps_https.as_path(), &j).as_ref(),
- )
- }
- "http" => {
- filename = deno_fs::normalize_path(
- get_cache_filename(self.deps_http.as_path(), &j).as_ref(),
- )
- }
- // TODO(kevinkassimo): change this to support other protocols than http
- _ => unimplemented!(),
- }
-
- debug!("module_name: {}, filename: {}", module_name, filename);
- Ok((module_name, filename))
- }
-}
-
-impl SourceMapGetter for DenoDir {
- fn get_source_map(&self, script_name: &str) -> Option<Vec<u8>> {
- match self.fetch_module_meta_data(script_name, ".") {
- Err(_e) => None,
- Ok(out) => match out.maybe_source_map {
- None => None,
- Some(source_map) => Some(source_map),
- },
- }
- }
-}
-
-fn get_cache_filename(basedir: &Path, url: &Url) -> PathBuf {
- let host = url.host_str().unwrap();
- let host_port = match url.port() {
- // Windows doesn't support ":" in filenames, so we represent port using a
- // special string.
- Some(port) => format!("{}_PORT{}", host, port),
- None => host.to_string(),
- };
-
- let mut out = basedir.to_path_buf();
- out.push(host_port);
- for path_seg in url.path_segments().unwrap() {
- out.push(path_seg);
- }
- out
-}
-
-fn source_code_hash(
- filename: &str,
- source_code: &[u8],
- version: &str,
-) -> String {
- let mut ctx = ring::digest::Context::new(&ring::digest::SHA1);
- ctx.update(version.as_bytes());
- ctx.update(filename.as_bytes());
- ctx.update(source_code);
- let digest = ctx.finish();
- let mut out = String::new();
- // TODO There must be a better way to do this...
- for byte in digest.as_ref() {
- write!(&mut out, "{:02x}", byte).unwrap();
- }
- out
-}
-
-fn is_remote(module_name: &str) -> bool {
- module_name.starts_with("http://") || module_name.starts_with("https://")
-}
-
-fn parse_local_or_remote(p: &str) -> Result<url::Url, url::ParseError> {
- if is_remote(p) || p.starts_with("file:") {
- Url::parse(p)
- } else {
- Url::from_file_path(p).map_err(|_err| url::ParseError::IdnaError)
- }
-}
-
-fn map_file_extension(path: &Path) -> msg::MediaType {
- match path.extension() {
- None => msg::MediaType::Unknown,
- Some(os_str) => match os_str.to_str() {
- Some("ts") => msg::MediaType::TypeScript,
- Some("js") => msg::MediaType::JavaScript,
- Some("json") => msg::MediaType::Json,
- _ => msg::MediaType::Unknown,
- },
- }
-}
-
-// convert a ContentType string into a enumerated MediaType
-fn map_content_type(path: &Path, content_type: Option<&str>) -> msg::MediaType {
- match content_type {
- Some(content_type) => {
- // sometimes there is additional data after the media type in
- // Content-Type so we have to do a bit of manipulation so we are only
- // dealing with the actual media type
- let ct_vector: Vec<&str> = content_type.split(';').collect();
- let ct: &str = ct_vector.first().unwrap();
- match ct.to_lowercase().as_ref() {
- "application/typescript"
- | "text/typescript"
- | "video/vnd.dlna.mpeg-tts"
- | "video/mp2t"
- | "application/x-typescript" => msg::MediaType::TypeScript,
- "application/javascript"
- | "text/javascript"
- | "application/ecmascript"
- | "text/ecmascript"
- | "application/x-javascript" => msg::MediaType::JavaScript,
- "application/json" | "text/json" => msg::MediaType::Json,
- "text/plain" => map_file_extension(path),
- _ => {
- debug!("unknown content type: {}", content_type);
- msg::MediaType::Unknown
- }
- }
- }
- None => map_file_extension(path),
- }
-}
-
-fn filter_shebang(bytes: Vec<u8>) -> Vec<u8> {
- let string = str::from_utf8(&bytes).unwrap();
- if let Some(i) = string.find('\n') {
- let (_, rest) = string.split_at(i);
- rest.as_bytes().to_owned()
- } else {
- Vec::new()
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use crate::tokio_util;
- use tempfile::TempDir;
-
- fn test_setup(reload: bool, recompile: bool) -> (TempDir, DenoDir) {
- let temp_dir = TempDir::new().expect("tempdir fail");
- let deno_dir =
- DenoDir::new(reload, recompile, Some(temp_dir.path().to_path_buf()))
- .expect("setup fail");
- (temp_dir, deno_dir)
- }
-
- // The `add_root` macro prepends "C:" to a string if on windows; on posix
- // systems it returns the input string untouched. This is necessary because
- // `Url::from_file_path()` fails if the input path isn't an absolute path.
- macro_rules! add_root {
- ($path:expr) => {
- if cfg!(target_os = "windows") {
- concat!("C:", $path)
- } else {
- $path
- }
- };
- }
-
- macro_rules! file_url {
- ($path:expr) => {
- if cfg!(target_os = "windows") {
- concat!("file:///C:", $path)
- } else {
- concat!("file://", $path)
- }
- };
- }
-
- #[test]
- fn test_get_cache_filename() {
- let url = Url::parse("http://example.com:1234/path/to/file.ts").unwrap();
- let basedir = Path::new("/cache/dir/");
- let cache_file = get_cache_filename(&basedir, &url);
- assert_eq!(
- cache_file,
- Path::new("/cache/dir/example.com_PORT1234/path/to/file.ts")
- );
- }
-
- #[test]
- fn test_cache_path() {
- let (temp_dir, deno_dir) = test_setup(false, false);
- let filename = "hello.js";
- let source_code = "1+2".as_bytes();
- let hash = source_code_hash(filename, source_code, version::DENO);
- assert_eq!(
- (
- temp_dir.path().join(format!("gen/{}.js", hash)),
- temp_dir.path().join(format!("gen/{}.js.map", hash))
- ),
- deno_dir.cache_path(filename, source_code)
- );
- }
-
- #[test]
- fn test_code_cache() {
- let (_temp_dir, deno_dir) = test_setup(false, false);
-
- let filename = "hello.js";
- let source_code = "1+2".as_bytes();
- let output_code = "1+2 // output code".as_bytes();
- let source_map = "{}".as_bytes();
- let hash = source_code_hash(filename, source_code, version::DENO);
- let (cache_path, source_map_path) =
- deno_dir.cache_path(filename, source_code);
- assert!(cache_path.ends_with(format!("gen/{}.js", hash)));
- assert!(source_map_path.ends_with(format!("gen/{}.js.map", hash)));
-
- let out = ModuleMetaData {
- filename: filename.to_owned(),
- source_code: source_code.to_owned(),
- module_name: "hello.js".to_owned(),
- media_type: msg::MediaType::TypeScript,
- maybe_output_code: Some(output_code.to_owned()),
- maybe_output_code_filename: None,
- maybe_source_map: Some(source_map.to_owned()),
- maybe_source_map_filename: None,
- };
-
- let r = deno_dir.code_cache(&out);
- r.expect("code_cache error");
- assert!(cache_path.exists());
- assert_eq!(output_code.to_owned(), fs::read(&cache_path).unwrap());
- }
-
- #[test]
- fn test_source_code_hash() {
- assert_eq!(
- "7e44de2ed9e0065da09d835b76b8d70be503d276",
- source_code_hash("hello.ts", "1+2".as_bytes(), "0.2.11")
- );
- // Different source_code should result in different hash.
- assert_eq!(
- "57033366cf9db1ef93deca258cdbcd9ef5f4bde1",
- source_code_hash("hello.ts", "1".as_bytes(), "0.2.11")
- );
- // Different filename should result in different hash.
- assert_eq!(
- "19657f90b5b0540f87679e2fb362e7bd62b644b0",
- source_code_hash("hi.ts", "1+2".as_bytes(), "0.2.11")
- );
- // Different version should result in different hash.
- assert_eq!(
- "e2b4b7162975a02bf2770f16836eb21d5bcb8be1",
- source_code_hash("hi.ts", "1+2".as_bytes(), "0.2.0")
- );
- }
-
- #[test]
- fn test_get_source_code_1() {
- let (temp_dir, deno_dir) = test_setup(false, false);
- // http_util::fetch_sync_string requires tokio
- tokio_util::init(|| {
- let module_name = "http://localhost:4545/tests/subdir/mod2.ts";
- let filename = deno_fs::normalize_path(
- deno_dir
- .deps_http
- .join("localhost_PORT4545/tests/subdir/mod2.ts")
- .as_ref(),
- );
- let mime_file_name = format!("{}.mime", &filename);
-
- let result = deno_dir.get_source_code(module_name, &filename);
- println!("module_name {} filename {}", module_name, filename);
- assert!(result.is_ok());
- let r = result.unwrap();
- assert_eq!(
- r.source_code,
- "export { printHello } from \"./print_hello.ts\";\n".as_bytes()
- );
- assert_eq!(&(r.media_type), &msg::MediaType::TypeScript);
- // Should not create .mime file due to matching ext
- assert!(fs::read_to_string(&mime_file_name).is_err());
-
- // Modify .mime
- let _ = fs::write(&mime_file_name, "text/javascript");
- let result2 = deno_dir.get_source_code(module_name, &filename);
- assert!(result2.is_ok());
- let r2 = result2.unwrap();
- assert_eq!(
- r2.source_code,
- "export { printHello } from \"./print_hello.ts\";\n".as_bytes()
- );
- // If get_source_code does not call remote, this should be JavaScript
- // as we modified before! (we do not overwrite .mime due to no http fetch)
- assert_eq!(&(r2.media_type), &msg::MediaType::JavaScript);
- assert_eq!(
- fs::read_to_string(&mime_file_name).unwrap(),
- "text/javascript"
- );
-
- // Force self.reload
- let deno_dir =
- DenoDir::new(true, false, Some(temp_dir.path().to_path_buf()))
- .expect("setup fail");
- let result3 = deno_dir.get_source_code(module_name, &filename);
- assert!(result3.is_ok());
- let r3 = result3.unwrap();
- let expected3 =
- "export { printHello } from \"./print_hello.ts\";\n".as_bytes();
- assert_eq!(r3.source_code, expected3);
- // Now the old .mime file should have gone! Resolved back to TypeScript
- assert_eq!(&(r3.media_type), &msg::MediaType::TypeScript);
- assert!(fs::read_to_string(&mime_file_name).is_err());
- });
- }
-
- #[test]
- fn test_get_source_code_2() {
- let (temp_dir, deno_dir) = test_setup(false, false);
- // http_util::fetch_sync_string requires tokio
- tokio_util::init(|| {
- let module_name = "http://localhost:4545/tests/subdir/mismatch_ext.ts";
- let filename = deno_fs::normalize_path(
- deno_dir
- .deps_http
- .join("localhost_PORT4545/tests/subdir/mismatch_ext.ts")
- .as_ref(),
- );
- let mime_file_name = format!("{}.mime", &filename);
-
- let result = deno_dir.get_source_code(module_name, &filename);
- println!("module_name {} filename {}", module_name, filename);
- assert!(result.is_ok());
- let r = result.unwrap();
- let expected = "export const loaded = true;\n".as_bytes();
- assert_eq!(r.source_code, expected);
- // Mismatch ext with content type, create .mime
- assert_eq!(&(r.media_type), &msg::MediaType::JavaScript);
- assert_eq!(
- fs::read_to_string(&mime_file_name).unwrap(),
- "text/javascript"
- );
-
- // Modify .mime
- let _ = fs::write(&mime_file_name, "text/typescript");
- let result2 = deno_dir.get_source_code(module_name, &filename);
- assert!(result2.is_ok());
- let r2 = result2.unwrap();
- let expected2 = "export const loaded = true;\n".as_bytes();
- assert_eq!(r2.source_code, expected2);
- // If get_source_code does not call remote, this should be TypeScript
- // as we modified before! (we do not overwrite .mime due to no http fetch)
- assert_eq!(&(r2.media_type), &msg::MediaType::TypeScript);
- assert_eq!(
- fs::read_to_string(&mime_file_name).unwrap(),
- "text/typescript"
- );
-
- // Force self.reload
- let deno_dir =
- DenoDir::new(true, false, Some(temp_dir.path().to_path_buf()))
- .expect("setup fail");
- let result3 = deno_dir.get_source_code(module_name, &filename);
- assert!(result3.is_ok());
- let r3 = result3.unwrap();
- let expected3 = "export const loaded = true;\n".as_bytes();
- assert_eq!(r3.source_code, expected3);
- // Now the old .mime file should be overwritten back to JavaScript!
- // (due to http fetch)
- assert_eq!(&(r3.media_type), &msg::MediaType::JavaScript);
- assert_eq!(
- fs::read_to_string(&mime_file_name).unwrap(),
- "text/javascript"
- );
- });
- }
-
- #[test]
- fn test_fetch_source_1() {
- use crate::tokio_util;
- // http_util::fetch_sync_string requires tokio
- tokio_util::init(|| {
- let (_temp_dir, deno_dir) = test_setup(false, false);
- let module_name =
- "http://localhost:4545/tests/subdir/mt_video_mp2t.t3.ts";
- let filename = deno_fs::normalize_path(
- deno_dir
- .deps_http
- .join("localhost_PORT4545/tests/subdir/mt_video_mp2t.t3.ts")
- .as_ref(),
- );
- let mime_file_name = format!("{}.mime", &filename);
-
- let result = deno_dir.fetch_remote_source(module_name, &filename);
- assert!(result.is_ok());
- let r = result.unwrap().unwrap();
- assert_eq!(r.source_code, "export const loaded = true;\n".as_bytes());
- assert_eq!(&(r.media_type), &msg::MediaType::TypeScript);
- // matching ext, no .mime file created
- assert!(fs::read_to_string(&mime_file_name).is_err());
-
- // Modify .mime, make sure read from local
- let _ = fs::write(&mime_file_name, "text/javascript");
- let result2 = deno_dir.fetch_local_source(module_name, &filename);
- assert!(result2.is_ok());
- let r2 = result2.unwrap().unwrap();
- assert_eq!(r2.source_code, "export const loaded = true;\n".as_bytes());
- // Not MediaType::TypeScript due to .mime modification
- assert_eq!(&(r2.media_type), &msg::MediaType::JavaScript);
- });
- }
-
- #[test]
- fn test_fetch_source_2() {
- use crate::tokio_util;
- // http_util::fetch_sync_string requires tokio
- tokio_util::init(|| {
- let (_temp_dir, deno_dir) = test_setup(false, false);
- let module_name = "http://localhost:4545/tests/subdir/no_ext";
- let filename = deno_fs::normalize_path(
- deno_dir
- .deps_http
- .join("localhost_PORT4545/tests/subdir/no_ext")
- .as_ref(),
- );
- let mime_file_name = format!("{}.mime", &filename);
- let result = deno_dir.fetch_remote_source(module_name, &filename);
- assert!(result.is_ok());
- let r = result.unwrap().unwrap();
- assert_eq!(r.source_code, "export const loaded = true;\n".as_bytes());
- assert_eq!(&(r.media_type), &msg::MediaType::TypeScript);
- // no ext, should create .mime file
- assert_eq!(
- fs::read_to_string(&mime_file_name).unwrap(),
- "text/typescript"
- );
-
- let module_name_2 = "http://localhost:4545/tests/subdir/mismatch_ext.ts";
- let filename_2 = deno_fs::normalize_path(
- deno_dir
- .deps_http
- .join("localhost_PORT4545/tests/subdir/mismatch_ext.ts")
- .as_ref(),
- );
- let mime_file_name_2 = format!("{}.mime", &filename_2);
- let result_2 = deno_dir.fetch_remote_source(module_name_2, &filename_2);
- assert!(result_2.is_ok());
- let r2 = result_2.unwrap().unwrap();
- assert_eq!(r2.source_code, "export const loaded = true;\n".as_bytes());
- assert_eq!(&(r2.media_type), &msg::MediaType::JavaScript);
- // mismatch ext, should create .mime file
- assert_eq!(
- fs::read_to_string(&mime_file_name_2).unwrap(),
- "text/javascript"
- );
-
- // test unknown extension
- let module_name_3 = "http://localhost:4545/tests/subdir/unknown_ext.deno";
- let filename_3 = deno_fs::normalize_path(
- deno_dir
- .deps_http
- .join("localhost_PORT4545/tests/subdir/unknown_ext.deno")
- .as_ref(),
- );
- let mime_file_name_3 = format!("{}.mime", &filename_3);
- let result_3 = deno_dir.fetch_remote_source(module_name_3, &filename_3);
- assert!(result_3.is_ok());
- let r3 = result_3.unwrap().unwrap();
- assert_eq!(r3.source_code, "export const loaded = true;\n".as_bytes());
- assert_eq!(&(r3.media_type), &msg::MediaType::TypeScript);
- // unknown ext, should create .mime file
- assert_eq!(
- fs::read_to_string(&mime_file_name_3).unwrap(),
- "text/typescript"
- );
- });
- }
-
- #[test]
- fn test_fetch_source_3() {
- // only local, no http_util::fetch_sync_string called
- let (_temp_dir, deno_dir) = test_setup(false, false);
- let cwd = std::env::current_dir().unwrap();
- let cwd_string = cwd.to_str().unwrap();
- let module_name = "http://example.com/mt_text_typescript.t1.ts"; // not used
- let filename =
- format!("{}/tests/subdir/mt_text_typescript.t1.ts", &cwd_string);
-
- let result = deno_dir.fetch_local_source(module_name, &filename);
- assert!(result.is_ok());
- let r = result.unwrap().unwrap();
- assert_eq!(r.source_code, "export const loaded = true;\n".as_bytes());
- assert_eq!(&(r.media_type), &msg::MediaType::TypeScript);
- }
-
- #[test]
- fn test_fetch_module_meta_data() {
- let (_temp_dir, deno_dir) = test_setup(false, false);
-
- let cwd = std::env::current_dir().unwrap();
- let cwd_string = String::from(cwd.to_str().unwrap()) + "/";
-
- // Test failure case.
- let specifier = "hello.ts";
- let referrer = add_root!("/baddir/badfile.ts");
- let r = deno_dir.fetch_module_meta_data(specifier, referrer);
- assert!(r.is_err());
-
- // Assuming cwd is the deno repo root.
- let specifier = "./js/main.ts";
- let referrer = cwd_string.as_str();
- let r = deno_dir.fetch_module_meta_data(specifier, referrer);
- assert!(r.is_ok());
- //let fetch_module_meta_data_output = r.unwrap();
- //println!("fetch_module_meta_data_output {:?}", fetch_module_meta_data_output);
- }
-
- #[test]
- fn test_fetch_module_meta_data_1() {
- /*recompile ts file*/
- let (_temp_dir, deno_dir) = test_setup(false, true);
-
- let cwd = std::env::current_dir().unwrap();
- let cwd_string = String::from(cwd.to_str().unwrap()) + "/";
-
- // Test failure case.
- let specifier = "hello.ts";
- let referrer = add_root!("/baddir/badfile.ts");
- let r = deno_dir.fetch_module_meta_data(specifier, referrer);
- assert!(r.is_err());
-
- // Assuming cwd is the deno repo root.
- let specifier = "./js/main.ts";
- let referrer = cwd_string.as_str();
- let r = deno_dir.fetch_module_meta_data(specifier, referrer);
- assert!(r.is_ok());
- }
-
- #[test]
- fn test_src_file_to_url_1() {
- let (_temp_dir, deno_dir) = test_setup(false, false);
- assert_eq!("hello", deno_dir.src_file_to_url("hello"));
- assert_eq!("/hello", deno_dir.src_file_to_url("/hello"));
- let x = deno_dir.deps_http.join("hello/world.txt");
- assert_eq!(
- "http://hello/world.txt",
- deno_dir.src_file_to_url(x.to_str().unwrap())
- );
- }
-
- #[test]
- fn test_src_file_to_url_2() {
- let (_temp_dir, deno_dir) = test_setup(false, false);
- assert_eq!("hello", deno_dir.src_file_to_url("hello"));
- assert_eq!("/hello", deno_dir.src_file_to_url("/hello"));
- let x = deno_dir.deps_https.join("hello/world.txt");
- assert_eq!(
- "https://hello/world.txt",
- deno_dir.src_file_to_url(x.to_str().unwrap())
- );
- }
-
- #[test]
- fn test_src_file_to_url_3() {
- let (_temp_dir, deno_dir) = test_setup(false, false);
- let x = deno_dir.deps_http.join("localhost_PORT4545/world.txt");
- assert_eq!(
- "http://localhost:4545/world.txt",
- deno_dir.src_file_to_url(x.to_str().unwrap())
- );
- }
-
- #[test]
- fn test_src_file_to_url_4() {
- let (_temp_dir, deno_dir) = test_setup(false, false);
- let x = deno_dir.deps_https.join("localhost_PORT4545/world.txt");
- assert_eq!(
- "https://localhost:4545/world.txt",
- deno_dir.src_file_to_url(x.to_str().unwrap())
- );
- }
-
- // https://github.com/denoland/deno/blob/golang/os_test.go#L16-L87
- #[test]
- fn test_resolve_module_1() {
- let (_temp_dir, deno_dir) = test_setup(false, false);
-
- let test_cases = [
- (
- "./subdir/print_hello.ts",
- add_root!("/Users/rld/go/src/github.com/denoland/deno/testdata/006_url_imports.ts"),
- file_url!("/Users/rld/go/src/github.com/denoland/deno/testdata/subdir/print_hello.ts"),
- add_root!("/Users/rld/go/src/github.com/denoland/deno/testdata/subdir/print_hello.ts"),
- ),
- (
- "testdata/001_hello.js",
- add_root!("/Users/rld/go/src/github.com/denoland/deno/"),
- file_url!("/Users/rld/go/src/github.com/denoland/deno/testdata/001_hello.js"),
- add_root!("/Users/rld/go/src/github.com/denoland/deno/testdata/001_hello.js"),
- ),
- (
- add_root!("/Users/rld/src/deno/hello.js"),
- ".",
- file_url!("/Users/rld/src/deno/hello.js"),
- add_root!("/Users/rld/src/deno/hello.js"),
- ),
- (
- add_root!("/this/module/got/imported.js"),
- add_root!("/that/module/did/it.js"),
- file_url!("/this/module/got/imported.js"),
- add_root!("/this/module/got/imported.js"),
- ),
- ];
- for &test in test_cases.iter() {
- let specifier = String::from(test.0);
- let referrer = String::from(test.1);
- let (module_name, filename) =
- deno_dir.resolve_module(&specifier, &referrer).unwrap();
- assert_eq!(module_name, test.2);
- assert_eq!(filename, test.3);
- }
- }
-
- #[test]
- fn test_resolve_module_2() {
- let (_temp_dir, deno_dir) = test_setup(false, false);
-
- let specifier = "http://localhost:4545/testdata/subdir/print_hello.ts";
- let referrer = add_root!("/deno/testdata/006_url_imports.ts");
-
- let expected_module_name =
- "http://localhost:4545/testdata/subdir/print_hello.ts";
- let expected_filename = deno_fs::normalize_path(
- deno_dir
- .deps_http
- .join("localhost_PORT4545/testdata/subdir/print_hello.ts")
- .as_ref(),
- );
-
- let (module_name, filename) =
- deno_dir.resolve_module(specifier, referrer).unwrap();
- assert_eq!(module_name, expected_module_name);
- assert_eq!(filename, expected_filename);
- }
-
- #[test]
- fn test_resolve_module_3() {
- let (_temp_dir, deno_dir) = test_setup(false, false);
-
- let specifier_ =
- deno_dir.deps_http.join("unpkg.com/liltest@0.0.5/index.ts");
- let specifier = specifier_.to_str().unwrap();
- let referrer = ".";
-
- let expected_module_name = "http://unpkg.com/liltest@0.0.5/index.ts";
- let expected_filename = deno_fs::normalize_path(
- deno_dir
- .deps_http
- .join("unpkg.com/liltest@0.0.5/index.ts")
- .as_ref(),
- );
-
- let (module_name, filename) =
- deno_dir.resolve_module(specifier, referrer).unwrap();
- assert_eq!(module_name, expected_module_name);
- assert_eq!(filename, expected_filename);
- }
-
- #[test]
- fn test_resolve_module_4() {
- let (_temp_dir, deno_dir) = test_setup(false, false);
-
- let specifier = "./util";
- let referrer_ = deno_dir.deps_http.join("unpkg.com/liltest@0.0.5/index.ts");
- let referrer = referrer_.to_str().unwrap();
-
- // http containing files -> load relative import with http
- let expected_module_name = "http://unpkg.com/liltest@0.0.5/util";
- let expected_filename = deno_fs::normalize_path(
- deno_dir
- .deps_http
- .join("unpkg.com/liltest@0.0.5/util")
- .as_ref(),
- );
-
- let (module_name, filename) =
- deno_dir.resolve_module(specifier, referrer).unwrap();
- assert_eq!(module_name, expected_module_name);
- assert_eq!(filename, expected_filename);
- }
-
- #[test]
- fn test_resolve_module_5() {
- let (_temp_dir, deno_dir) = test_setup(false, false);
-
- let specifier = "./util";
- let referrer_ =
- deno_dir.deps_https.join("unpkg.com/liltest@0.0.5/index.ts");
- let referrer = referrer_.to_str().unwrap();
-
- // https containing files -> load relative import with https
- let expected_module_name = "https://unpkg.com/liltest@0.0.5/util";
- let expected_filename = deno_fs::normalize_path(
- deno_dir
- .deps_https
- .join("unpkg.com/liltest@0.0.5/util")
- .as_ref(),
- );
-
- let (module_name, filename) =
- deno_dir.resolve_module(specifier, referrer).unwrap();
- assert_eq!(module_name, expected_module_name);
- assert_eq!(filename, expected_filename);
- }
-
- #[test]
- fn test_resolve_module_6() {
- let (_temp_dir, deno_dir) = test_setup(false, false);
-
- let specifier = "http://localhost:4545/tests/subdir/mod2.ts";
- let referrer = add_root!("/deno/tests/006_url_imports.ts");
- let expected_module_name = "http://localhost:4545/tests/subdir/mod2.ts";
- let expected_filename = deno_fs::normalize_path(
- deno_dir
- .deps_http
- .join("localhost_PORT4545/tests/subdir/mod2.ts")
- .as_ref(),
- );
-
- let (module_name, filename) =
- deno_dir.resolve_module(specifier, referrer).unwrap();
- assert_eq!(module_name, expected_module_name);
- assert_eq!(filename, expected_filename);
- }
-
- #[test]
- fn test_resolve_module_7() {
- let (_temp_dir, deno_dir) = test_setup(false, false);
-
- let specifier = "http_test.ts";
- let referrer = add_root!("/Users/rld/src/deno_net/");
- let expected_module_name =
- file_url!("/Users/rld/src/deno_net/http_test.ts");
- let expected_filename = add_root!("/Users/rld/src/deno_net/http_test.ts");
-
- let (module_name, filename) =
- deno_dir.resolve_module(specifier, referrer).unwrap();
- assert_eq!(module_name, expected_module_name);
- assert_eq!(filename, expected_filename);
- }
-
- #[test]
- fn test_resolve_module_referrer_dot() {
- let (_temp_dir, deno_dir) = test_setup(false, false);
-
- let specifier = "tests/001_hello.js";
-
- let cwd = std::env::current_dir().unwrap();
- let expected_path = cwd.join(specifier);
- let expected_module_name =
- Url::from_file_path(&expected_path).unwrap().to_string();
- let expected_filename = deno_fs::normalize_path(&expected_path);
-
- let (module_name, filename) =
- deno_dir.resolve_module(specifier, ".").unwrap();
- assert_eq!(module_name, expected_module_name);
- assert_eq!(filename, expected_filename);
-
- let (module_name, filename) =
- deno_dir.resolve_module(specifier, "./").unwrap();
- assert_eq!(module_name, expected_module_name);
- assert_eq!(filename, expected_filename);
- }
-
- #[test]
- fn test_resolve_module_referrer_dotdot() {
- let (_temp_dir, deno_dir) = test_setup(false, false);
-
- let specifier = "tests/001_hello.js";
-
- let cwd = std::env::current_dir().unwrap();
- let expected_path = cwd.join("..").join(specifier);
- let expected_module_name =
- Url::from_file_path(&expected_path).unwrap().to_string();
- let expected_filename = deno_fs::normalize_path(&expected_path);
-
- let (module_name, filename) =
- deno_dir.resolve_module(specifier, "..").unwrap();
- assert_eq!(module_name, expected_module_name);
- assert_eq!(filename, expected_filename);
-
- let (module_name, filename) =
- deno_dir.resolve_module(specifier, "../").unwrap();
- assert_eq!(module_name, expected_module_name);
- assert_eq!(filename, expected_filename);
- }
-
- #[test]
- fn test_map_file_extension() {
- assert_eq!(
- map_file_extension(Path::new("foo/bar.ts")),
- msg::MediaType::TypeScript
- );
- assert_eq!(
- map_file_extension(Path::new("foo/bar.d.ts")),
- msg::MediaType::TypeScript
- );
- assert_eq!(
- map_file_extension(Path::new("foo/bar.js")),
- msg::MediaType::JavaScript
- );
- assert_eq!(
- map_file_extension(Path::new("foo/bar.json")),
- msg::MediaType::Json
- );
- assert_eq!(
- map_file_extension(Path::new("foo/bar.txt")),
- msg::MediaType::Unknown
- );
- assert_eq!(
- map_file_extension(Path::new("foo/bar")),
- msg::MediaType::Unknown
- );
- }
-
- #[test]
- fn test_map_content_type() {
- // Extension only
- assert_eq!(
- map_content_type(Path::new("foo/bar.ts"), None),
- msg::MediaType::TypeScript
- );
- assert_eq!(
- map_content_type(Path::new("foo/bar.d.ts"), None),
- msg::MediaType::TypeScript
- );
- assert_eq!(
- map_content_type(Path::new("foo/bar.js"), None),
- msg::MediaType::JavaScript
- );
- assert_eq!(
- map_content_type(Path::new("foo/bar.json"), None),
- msg::MediaType::Json
- );
- assert_eq!(
- map_content_type(Path::new("foo/bar.txt"), None),
- msg::MediaType::Unknown
- );
- assert_eq!(
- map_content_type(Path::new("foo/bar"), None),
- msg::MediaType::Unknown
- );
-
- // Media Type
- assert_eq!(
- map_content_type(Path::new("foo/bar"), Some("application/typescript")),
- msg::MediaType::TypeScript
- );
- assert_eq!(
- map_content_type(Path::new("foo/bar"), Some("text/typescript")),
- msg::MediaType::TypeScript
- );
- assert_eq!(
- map_content_type(Path::new("foo/bar"), Some("video/vnd.dlna.mpeg-tts")),
- msg::MediaType::TypeScript
- );
- assert_eq!(
- map_content_type(Path::new("foo/bar"), Some("video/mp2t")),
- msg::MediaType::TypeScript
- );
- assert_eq!(
- map_content_type(Path::new("foo/bar"), Some("application/x-typescript")),
- msg::MediaType::TypeScript
- );
- assert_eq!(
- map_content_type(Path::new("foo/bar"), Some("application/javascript")),
- msg::MediaType::JavaScript
- );
- assert_eq!(
- map_content_type(Path::new("foo/bar"), Some("text/javascript")),
- msg::MediaType::JavaScript
- );
- assert_eq!(
- map_content_type(Path::new("foo/bar"), Some("application/ecmascript")),
- msg::MediaType::JavaScript
- );
- assert_eq!(
- map_content_type(Path::new("foo/bar"), Some("text/ecmascript")),
- msg::MediaType::JavaScript
- );
- assert_eq!(
- map_content_type(Path::new("foo/bar"), Some("application/x-javascript")),
- msg::MediaType::JavaScript
- );
- assert_eq!(
- map_content_type(Path::new("foo/bar"), Some("application/json")),
- msg::MediaType::Json
- );
- assert_eq!(
- map_content_type(Path::new("foo/bar"), Some("text/json")),
- msg::MediaType::Json
- );
- assert_eq!(
- map_content_type(Path::new("foo/bar.ts"), Some("text/plain")),
- msg::MediaType::TypeScript
- );
- assert_eq!(
- map_content_type(Path::new("foo/bar.ts"), Some("foo/bar")),
- msg::MediaType::Unknown
- );
- }
-
- #[test]
- fn test_filter_shebang() {
- assert_eq!(filter_shebang("#!".as_bytes().to_owned()), "".as_bytes());
- assert_eq!(
- filter_shebang("#!\n\n".as_bytes().to_owned()),
- "\n\n".as_bytes()
- );
- let code = "#!/usr/bin/env deno\nconsole.log('hello');\n"
- .as_bytes()
- .to_owned();
- assert_eq!(filter_shebang(code), "\nconsole.log('hello');\n".as_bytes());
- }
-}
diff --git a/src/errors.rs b/src/errors.rs
deleted file mode 100644
index 65118d070..000000000
--- a/src/errors.rs
+++ /dev/null
@@ -1,207 +0,0 @@
-// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-use crate::js_errors::JSErrorColor;
-pub use crate::msg::ErrorKind;
-use crate::resolve_addr::ResolveAddrError;
-use deno_core::JSError;
-use hyper;
-use std;
-use std::fmt;
-use std::io;
-use url;
-
-pub type DenoResult<T> = std::result::Result<T, DenoError>;
-
-#[derive(Debug)]
-pub struct DenoError {
- repr: Repr,
-}
-
-#[derive(Debug)]
-enum Repr {
- Simple(ErrorKind, String),
- IoErr(io::Error),
- UrlErr(url::ParseError),
- HyperErr(hyper::Error),
-}
-
-pub fn new(kind: ErrorKind, msg: String) -> DenoError {
- DenoError {
- repr: Repr::Simple(kind, msg),
- }
-}
-
-impl DenoError {
- pub fn kind(&self) -> ErrorKind {
- match self.repr {
- Repr::Simple(kind, ref _msg) => kind,
- // Repr::Simple(kind) => kind,
- Repr::IoErr(ref err) => {
- use std::io::ErrorKind::*;
- match err.kind() {
- NotFound => ErrorKind::NotFound,
- PermissionDenied => ErrorKind::PermissionDenied,
- ConnectionRefused => ErrorKind::ConnectionRefused,
- ConnectionReset => ErrorKind::ConnectionReset,
- ConnectionAborted => ErrorKind::ConnectionAborted,
- NotConnected => ErrorKind::NotConnected,
- AddrInUse => ErrorKind::AddrInUse,
- AddrNotAvailable => ErrorKind::AddrNotAvailable,
- BrokenPipe => ErrorKind::BrokenPipe,
- AlreadyExists => ErrorKind::AlreadyExists,
- WouldBlock => ErrorKind::WouldBlock,
- InvalidInput => ErrorKind::InvalidInput,
- InvalidData => ErrorKind::InvalidData,
- TimedOut => ErrorKind::TimedOut,
- Interrupted => ErrorKind::Interrupted,
- WriteZero => ErrorKind::WriteZero,
- Other => ErrorKind::Other,
- UnexpectedEof => ErrorKind::UnexpectedEof,
- _ => unreachable!(),
- }
- }
- Repr::UrlErr(ref err) => {
- use url::ParseError::*;
- match err {
- EmptyHost => ErrorKind::EmptyHost,
- IdnaError => ErrorKind::IdnaError,
- InvalidPort => ErrorKind::InvalidPort,
- InvalidIpv4Address => ErrorKind::InvalidIpv4Address,
- InvalidIpv6Address => ErrorKind::InvalidIpv6Address,
- InvalidDomainCharacter => ErrorKind::InvalidDomainCharacter,
- RelativeUrlWithoutBase => ErrorKind::RelativeUrlWithoutBase,
- RelativeUrlWithCannotBeABaseBase => {
- ErrorKind::RelativeUrlWithCannotBeABaseBase
- }
- SetHostOnCannotBeABaseUrl => ErrorKind::SetHostOnCannotBeABaseUrl,
- Overflow => ErrorKind::Overflow,
- }
- }
- Repr::HyperErr(ref err) => {
- // For some reason hyper::errors::Kind is private.
- if err.is_parse() {
- ErrorKind::HttpParse
- } else if err.is_user() {
- ErrorKind::HttpUser
- } else if err.is_canceled() {
- ErrorKind::HttpCanceled
- } else if err.is_closed() {
- ErrorKind::HttpClosed
- } else {
- ErrorKind::HttpOther
- }
- }
- }
- }
-}
-
-impl fmt::Display for DenoError {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self.repr {
- Repr::Simple(_kind, ref err_str) => f.pad(err_str),
- Repr::IoErr(ref err) => err.fmt(f),
- Repr::UrlErr(ref err) => err.fmt(f),
- Repr::HyperErr(ref err) => err.fmt(f),
- }
- }
-}
-
-impl std::error::Error for DenoError {
- fn description(&self) -> &str {
- match self.repr {
- Repr::Simple(_kind, ref msg) => msg.as_str(),
- Repr::IoErr(ref err) => err.description(),
- Repr::UrlErr(ref err) => err.description(),
- Repr::HyperErr(ref err) => err.description(),
- }
- }
-
- fn cause(&self) -> Option<&dyn std::error::Error> {
- match self.repr {
- Repr::Simple(_kind, ref _msg) => None,
- Repr::IoErr(ref err) => Some(err),
- Repr::UrlErr(ref err) => Some(err),
- Repr::HyperErr(ref err) => Some(err),
- }
- }
-}
-
-impl From<io::Error> for DenoError {
- #[inline]
- fn from(err: io::Error) -> Self {
- Self {
- repr: Repr::IoErr(err),
- }
- }
-}
-
-impl From<url::ParseError> for DenoError {
- #[inline]
- fn from(err: url::ParseError) -> Self {
- Self {
- repr: Repr::UrlErr(err),
- }
- }
-}
-
-impl From<hyper::Error> for DenoError {
- #[inline]
- fn from(err: hyper::Error) -> Self {
- Self {
- repr: Repr::HyperErr(err),
- }
- }
-}
-
-impl From<ResolveAddrError> for DenoError {
- fn from(e: ResolveAddrError) -> Self {
- match e {
- ResolveAddrError::Syntax => Self {
- repr: Repr::Simple(
- ErrorKind::InvalidInput,
- "invalid address syntax".to_string(),
- ),
- },
- ResolveAddrError::Resolution(io_err) => Self {
- repr: Repr::IoErr(io_err),
- },
- }
- }
-}
-
-pub fn bad_resource() -> DenoError {
- new(ErrorKind::BadResource, String::from("bad resource id"))
-}
-
-pub fn permission_denied() -> DenoError {
- new(
- ErrorKind::PermissionDenied,
- String::from("permission denied"),
- )
-}
-
-#[derive(Debug)]
-pub enum RustOrJsError {
- Rust(DenoError),
- Js(JSError),
-}
-
-impl From<DenoError> for RustOrJsError {
- fn from(e: DenoError) -> Self {
- RustOrJsError::Rust(e)
- }
-}
-
-impl From<JSError> for RustOrJsError {
- fn from(e: JSError) -> Self {
- RustOrJsError::Js(e)
- }
-}
-
-impl fmt::Display for RustOrJsError {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- RustOrJsError::Rust(e) => e.fmt(f),
- RustOrJsError::Js(e) => JSErrorColor(e).fmt(f),
- }
- }
-}
diff --git a/src/flags.rs b/src/flags.rs
deleted file mode 100644
index d6a63a9fb..000000000
--- a/src/flags.rs
+++ /dev/null
@@ -1,291 +0,0 @@
-// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-use deno_core::v8_set_flags;
-use getopts;
-use getopts::Options;
-
-// Creates vector of strings, Vec<String>
-#[cfg(test)]
-macro_rules! svec {
- ($($x:expr),*) => (vec![$($x.to_string()),*]);
-}
-
-#[cfg_attr(feature = "cargo-clippy", allow(stutter))]
-#[derive(Clone, Debug, PartialEq, Default)]
-pub struct DenoFlags {
- pub help: bool,
- pub log_debug: bool,
- pub version: bool,
- pub reload: bool,
- pub recompile: bool,
- pub allow_read: bool,
- pub allow_write: bool,
- pub allow_net: bool,
- pub allow_env: bool,
- pub allow_run: bool,
- pub no_prompts: bool,
- pub types: bool,
- pub prefetch: bool,
- pub info: bool,
- pub fmt: bool,
-}
-
-pub fn get_usage(opts: &Options) -> String {
- format!(
- "Usage: deno script.ts {}
-Environment variables:
- DENO_DIR Set deno's base directory
- NO_COLOR Set to disable color",
- opts.usage("")
- )
-}
-
-/// Checks provided arguments for known options and sets appropriate Deno flags
-/// for them. Unknown options are returned for further use.
-/// Note:
-///
-/// 1. This assumes that privileged flags do not accept parameters deno --foo bar.
-/// This assumption is currently valid. But if it were to change in the future,
-/// this parsing technique would need to be modified. I think we want to keep the
-/// privileged flags minimal - so having this restriction is maybe a good thing.
-///
-/// 2. Misspelled flags will be forwarded to user code - e.g. --allow-ne would
-/// not cause an error. I also think this is ok because missing any of the
-/// privileged flags is not destructive. Userland flag parsing would catch these
-/// errors.
-fn set_recognized_flags(
- opts: &Options,
- flags: &mut DenoFlags,
- args: Vec<String>,
-) -> Result<Vec<String>, getopts::Fail> {
- let mut rest = Vec::<String>::new();
- // getopts doesn't allow parsing unknown options so we check them
- // one-by-one and handle unrecognized ones manually
- // better solution welcome!
- for arg in args {
- let fake_args = vec![arg];
- match opts.parse(&fake_args) {
- Err(getopts::Fail::UnrecognizedOption(_)) => {
- rest.extend(fake_args);
- }
- Err(e) => {
- return Err(e);
- }
- Ok(matches) => {
- if matches.opt_present("help") {
- flags.help = true;
- }
- if matches.opt_present("log-debug") {
- flags.log_debug = true;
- }
- if matches.opt_present("version") {
- flags.version = true;
- }
- if matches.opt_present("reload") {
- flags.reload = true;
- }
- if matches.opt_present("recompile") {
- flags.recompile = true;
- }
- if matches.opt_present("allow-read") {
- flags.allow_read = true;
- }
- if matches.opt_present("allow-write") {
- flags.allow_write = true;
- }
- if matches.opt_present("allow-net") {
- flags.allow_net = true;
- }
- if matches.opt_present("allow-env") {
- flags.allow_env = true;
- }
- if matches.opt_present("allow-run") {
- flags.allow_run = true;
- }
- if matches.opt_present("allow-all") {
- flags.allow_read = true;
- flags.allow_env = true;
- flags.allow_net = true;
- flags.allow_run = true;
- flags.allow_read = true;
- flags.allow_write = true;
- }
- if matches.opt_present("no-prompt") {
- flags.no_prompts = true;
- }
- if matches.opt_present("types") {
- flags.types = true;
- }
- if matches.opt_present("prefetch") {
- flags.prefetch = true;
- }
- if matches.opt_present("info") {
- flags.info = true;
- }
- if matches.opt_present("fmt") {
- flags.fmt = true;
- }
-
- if !matches.free.is_empty() {
- rest.extend(matches.free);
- }
- }
- }
- }
- Ok(rest)
-}
-
-#[cfg_attr(feature = "cargo-clippy", allow(stutter))]
-pub fn set_flags(
- args: Vec<String>,
-) -> Result<(DenoFlags, Vec<String>, String), String> {
- // TODO: all flags passed after "--" are swallowed by v8_set_flags
- // eg. deno --allow-net ./test.ts -- --title foobar
- // args === ["deno", "--allow-net" "./test.ts"]
- let args = v8_set_flags(args);
-
- let mut opts = Options::new();
- // TODO(kevinkassimo): v8_set_flags intercepts '-help' with single '-'
- // Resolve that and then uncomment line below (enabling Go style -long-flag)
- // opts.long_only(true);
- opts.optflag("", "allow-read", "Allow file system read access");
- opts.optflag("", "allow-write", "Allow file system write access");
- opts.optflag("", "allow-net", "Allow network access");
- opts.optflag("", "allow-env", "Allow environment access");
- opts.optflag("", "allow-run", "Allow running subprocesses");
- opts.optflag("A", "allow-all", "Allow all permissions");
- opts.optflag("", "no-prompt", "Do not use prompts");
- opts.optflag("", "recompile", "Force recompilation of TypeScript code");
- opts.optflag("h", "help", "Print this message");
- opts.optflag("D", "log-debug", "Log debug output");
- opts.optflag("v", "version", "Print the version");
- opts.optflag("r", "reload", "Reload cached remote resources");
- opts.optflag("", "v8-options", "Print V8 command line options");
- opts.optflag("", "types", "Print runtime TypeScript declarations");
- opts.optflag("", "prefetch", "Prefetch the dependencies");
- opts.optflag("", "info", "Show source file related info");
- opts.optflag("", "fmt", "Format code");
-
- let mut flags = DenoFlags::default();
-
- let rest =
- set_recognized_flags(&opts, &mut flags, args).map_err(|e| e.to_string())?;
- Ok((flags, rest, get_usage(&opts)))
-}
-
-#[test]
-fn test_set_flags_1() {
- let (flags, rest, _) = set_flags(svec!["deno", "--version"]).unwrap();
- assert_eq!(rest, svec!["deno"]);
- assert_eq!(
- flags,
- DenoFlags {
- version: true,
- ..DenoFlags::default()
- }
- );
-}
-
-#[test]
-fn test_set_flags_2() {
- let (flags, rest, _) =
- set_flags(svec!["deno", "-r", "-D", "script.ts"]).unwrap();
- assert_eq!(rest, svec!["deno", "script.ts"]);
- assert_eq!(
- flags,
- DenoFlags {
- log_debug: true,
- reload: true,
- ..DenoFlags::default()
- }
- );
-}
-
-#[test]
-fn test_set_flags_3() {
- let (flags, rest, _) =
- set_flags(svec!["deno", "-r", "script.ts", "--allow-write"]).unwrap();
- assert_eq!(rest, svec!["deno", "script.ts"]);
- assert_eq!(
- flags,
- DenoFlags {
- reload: true,
- allow_write: true,
- ..DenoFlags::default()
- }
- );
-}
-
-#[test]
-fn test_set_flags_4() {
- let (flags, rest, _) =
- set_flags(svec!["deno", "-Dr", "script.ts", "--allow-write"]).unwrap();
- assert_eq!(rest, svec!["deno", "script.ts"]);
- assert_eq!(
- flags,
- DenoFlags {
- log_debug: true,
- reload: true,
- allow_write: true,
- ..DenoFlags::default()
- }
- );
-}
-
-#[test]
-fn test_set_flags_5() {
- let (flags, rest, _) = set_flags(svec!["deno", "--types"]).unwrap();
- assert_eq!(rest, svec!["deno"]);
- assert_eq!(
- flags,
- DenoFlags {
- types: true,
- ..DenoFlags::default()
- }
- )
-}
-
-#[test]
-fn test_set_flags_6() {
- let (flags, rest, _) =
- set_flags(svec!["deno", "gist.ts", "--title", "X", "--allow-net"]).unwrap();
- assert_eq!(rest, svec!["deno", "gist.ts", "--title", "X"]);
- assert_eq!(
- flags,
- DenoFlags {
- allow_net: true,
- ..DenoFlags::default()
- }
- )
-}
-
-#[test]
-fn test_set_flags_7() {
- let (flags, rest, _) =
- set_flags(svec!["deno", "gist.ts", "--allow-all"]).unwrap();
- assert_eq!(rest, svec!["deno", "gist.ts"]);
- assert_eq!(
- flags,
- DenoFlags {
- allow_net: true,
- allow_env: true,
- allow_run: true,
- allow_read: true,
- allow_write: true,
- ..DenoFlags::default()
- }
- )
-}
-
-#[test]
-fn test_set_flags_8() {
- let (flags, rest, _) =
- set_flags(svec!["deno", "gist.ts", "--allow-read"]).unwrap();
- assert_eq!(rest, svec!["deno", "gist.ts"]);
- assert_eq!(
- flags,
- DenoFlags {
- allow_read: true,
- ..DenoFlags::default()
- }
- )
-}
diff --git a/src/fs.rs b/src/fs.rs
deleted file mode 100644
index ff0da95e5..000000000
--- a/src/fs.rs
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-use std;
-use std::fs::{create_dir, DirBuilder, File, OpenOptions};
-use std::io::ErrorKind;
-use std::io::Write;
-use std::path::{Path, PathBuf};
-
-use rand;
-use rand::Rng;
-
-#[cfg(any(unix))]
-use std::os::unix::fs::DirBuilderExt;
-#[cfg(any(unix))]
-use std::os::unix::fs::PermissionsExt;
-
-pub fn write_file<T: AsRef<[u8]>>(
- filename: &Path,
- data: T,
- perm: u32,
-) -> std::io::Result<()> {
- write_file_2(filename, data, true, perm, true, false)
-}
-
-pub fn write_file_2<T: AsRef<[u8]>>(
- filename: &Path,
- data: T,
- update_perm: bool,
- perm: u32,
- is_create: bool,
- is_append: bool,
-) -> std::io::Result<()> {
- let mut file = OpenOptions::new()
- .read(false)
- .write(true)
- .append(is_append)
- .truncate(!is_append)
- .create(is_create)
- .open(filename)?;
-
- if update_perm {
- set_permissions(&mut file, perm)?;
- }
-
- file.write_all(data.as_ref())
-}
-
-#[cfg(any(unix))]
-fn set_permissions(file: &mut File, perm: u32) -> std::io::Result<()> {
- debug!("set file perm to {}", perm);
- file.set_permissions(PermissionsExt::from_mode(perm & 0o777))
-}
-#[cfg(not(any(unix)))]
-fn set_permissions(_file: &mut File, _perm: u32) -> std::io::Result<()> {
- // NOOP on windows
- Ok(())
-}
-
-pub fn make_temp_dir(
- dir: Option<&Path>,
- prefix: Option<&str>,
- suffix: Option<&str>,
-) -> std::io::Result<PathBuf> {
- let prefix_ = prefix.unwrap_or("");
- let suffix_ = suffix.unwrap_or("");
- let mut buf: PathBuf = match dir {
- Some(ref p) => p.to_path_buf(),
- None => std::env::temp_dir(),
- }.join("_");
- let mut rng = rand::thread_rng();
- loop {
- let unique = rng.gen::<u32>();
- buf.set_file_name(format!("{}{:08x}{}", prefix_, unique, suffix_));
- // TODO: on posix, set mode flags to 0o700.
- let r = create_dir(buf.as_path());
- match r {
- Err(ref e) if e.kind() == ErrorKind::AlreadyExists => continue,
- Ok(_) => return Ok(buf),
- Err(e) => return Err(e),
- }
- }
-}
-
-pub fn mkdir(path: &Path, perm: u32, recursive: bool) -> std::io::Result<()> {
- debug!("mkdir -p {}", path.display());
- let mut builder = DirBuilder::new();
- builder.recursive(recursive);
- set_dir_permission(&mut builder, perm);
- builder.create(path)
-}
-
-#[cfg(any(unix))]
-fn set_dir_permission(builder: &mut DirBuilder, perm: u32) {
- debug!("set dir perm to {}", perm);
- builder.mode(perm & 0o777);
-}
-
-#[cfg(not(any(unix)))]
-fn set_dir_permission(_builder: &mut DirBuilder, _perm: u32) {
- // NOOP on windows
-}
-
-pub fn normalize_path(path: &Path) -> String {
- let s = String::from(path.to_str().unwrap());
- if cfg!(windows) {
- // TODO This isn't correct. Probbly should iterate over components.
- s.replace("\\", "/")
- } else {
- s
- }
-}
diff --git a/src/global_timer.rs b/src/global_timer.rs
deleted file mode 100644
index eef70ddc2..000000000
--- a/src/global_timer.rs
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2018-2019 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 crate::tokio_util::panic_on_error;
-use futures::Future;
-use std::time::Instant;
-use tokio::sync::oneshot;
-use tokio::timer::Delay;
-
-pub struct GlobalTimer {
- tx: Option<oneshot::Sender<()>>,
-}
-
-impl GlobalTimer {
- pub fn new() -> Self {
- Self { tx: None }
- }
-
- 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<Item = (), Error = ()> {
- if self.tx.is_some() {
- self.cancel();
- }
- assert!(self.tx.is_none());
-
- let (tx, rx) = oneshot::channel();
- self.tx = Some(tx);
-
- let delay = panic_on_error(Delay::new(deadline));
- let rx = panic_on_error(rx);
-
- delay.select(rx).then(|_| Ok(()))
- }
-}
diff --git a/src/http_body.rs b/src/http_body.rs
deleted file mode 100644
index 235463ff1..000000000
--- a/src/http_body.rs
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-
-use futures::Async;
-use futures::Poll;
-use hyper::body::Payload;
-use hyper::Body;
-use hyper::Chunk;
-use std::cmp::min;
-use std::io;
-use std::io::Read;
-use tokio::io::AsyncRead;
-
-/// Wraps `hyper::Body` so that it can be exposed as an `AsyncRead` and integrated
-/// into resources more easily.
-pub struct HttpBody {
- body: Body,
- chunk: Option<Chunk>,
- pos: usize,
-}
-
-impl HttpBody {
- pub fn from(body: Body) -> Self {
- Self {
- body,
- chunk: None,
- pos: 0,
- }
- }
-}
-
-impl Read for HttpBody {
- fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
- unimplemented!();
- }
-}
-
-impl AsyncRead for HttpBody {
- fn poll_read(&mut self, buf: &mut [u8]) -> Poll<usize, io::Error> {
- if let Some(chunk) = self.chunk.take() {
- debug!(
- "HttpBody Fake Read buf {} chunk {} pos {}",
- buf.len(),
- chunk.len(),
- self.pos
- );
- let n = min(buf.len(), chunk.len() - self.pos);
- {
- let rest = &chunk[self.pos..];
- buf[..n].clone_from_slice(&rest[..n]);
- }
- self.pos += n;
- if self.pos == chunk.len() {
- self.pos = 0;
- } else {
- self.chunk = Some(chunk);
- }
- return Ok(Async::Ready(n));
- } else {
- assert_eq!(self.pos, 0);
- }
-
- let p = self.body.poll_data();
- match p {
- Err(e) => Err(
- // TODO Need to map hyper::Error into std::io::Error.
- io::Error::new(io::ErrorKind::Other, e),
- ),
- Ok(Async::NotReady) => Ok(Async::NotReady),
- Ok(Async::Ready(maybe_chunk)) => match maybe_chunk {
- None => Ok(Async::Ready(0)),
- Some(chunk) => {
- debug!(
- "HttpBody Real Read buf {} chunk {} pos {}",
- buf.len(),
- chunk.len(),
- self.pos
- );
- let n = min(buf.len(), chunk.len());
- buf[..n].clone_from_slice(&chunk[..n]);
- if buf.len() < chunk.len() {
- self.pos = n;
- self.chunk = Some(chunk);
- }
- Ok(Async::Ready(n))
- }
- },
- }
- }
-}
-
-#[test]
-fn test_body_async_read() {
- use std::str::from_utf8;
- let body = Body::from("hello world");
- let mut body = HttpBody::from(body);
-
- let buf = &mut [0, 0, 0, 0, 0];
- let r = body.poll_read(buf);
- assert!(r.is_ok());
- assert_eq!(r.unwrap(), Async::Ready(5));
- assert_eq!(from_utf8(buf).unwrap(), "hello");
-
- let r = body.poll_read(buf);
- assert!(r.is_ok());
- assert_eq!(r.unwrap(), Async::Ready(5));
- assert_eq!(from_utf8(buf).unwrap(), " worl");
-
- let r = body.poll_read(buf);
- assert!(r.is_ok());
- assert_eq!(r.unwrap(), Async::Ready(1));
- assert_eq!(from_utf8(&buf[0..1]).unwrap(), "d");
-}
diff --git a/src/http_util.rs b/src/http_util.rs
deleted file mode 100644
index 8aadbe136..000000000
--- a/src/http_util.rs
+++ /dev/null
@@ -1,166 +0,0 @@
-// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-use crate::errors;
-use crate::errors::{DenoError, DenoResult};
-use crate::tokio_util;
-
-use futures::future::{loop_fn, Loop};
-use futures::{future, Future, Stream};
-use hyper;
-use hyper::client::{Client, HttpConnector};
-use hyper::header::CONTENT_TYPE;
-use hyper::Uri;
-use hyper_rustls;
-
-type Connector = hyper_rustls::HttpsConnector<HttpConnector>;
-
-lazy_static! {
- static ref CONNECTOR: Connector = {
- let num_dns_threads = 4;
- Connector::new(num_dns_threads)
- };
-}
-
-pub fn get_client() -> Client<Connector, hyper::Body> {
- // TODO use Hyper's connection pool.
- let c = CONNECTOR.clone();
- Client::builder().build(c)
-}
-
-/// Construct the next uri based on base uri and location header fragment
-/// See <https://tools.ietf.org/html/rfc3986#section-4.2>
-fn resolve_uri_from_location(base_uri: &Uri, location: &str) -> Uri {
- if location.starts_with("http://") || location.starts_with("https://") {
- // absolute uri
- location
- .parse::<Uri>()
- .expect("provided redirect url should be a valid url")
- } else if location.starts_with("//") {
- // "//" authority path-abempty
- format!("{}:{}", base_uri.scheme_part().unwrap().as_str(), location)
- .parse::<Uri>()
- .expect("provided redirect url should be a valid url")
- } else if location.starts_with('/') {
- // path-absolute
- let mut new_uri_parts = base_uri.clone().into_parts();
- new_uri_parts.path_and_query = Some(location.parse().unwrap());
- Uri::from_parts(new_uri_parts).unwrap()
- } else {
- // assuming path-noscheme | path-empty
- let mut new_uri_parts = base_uri.clone().into_parts();
- new_uri_parts.path_and_query =
- Some(format!("{}/{}", base_uri.path(), location).parse().unwrap());
- Uri::from_parts(new_uri_parts).unwrap()
- }
-}
-
-// The CodeFetch message is used to load HTTP javascript resources and expects a
-// synchronous response, this utility method supports that.
-pub fn fetch_sync_string(module_name: &str) -> DenoResult<(String, String)> {
- let url = module_name.parse::<Uri>().unwrap();
- let client = get_client();
- // TODO(kevinkassimo): consider set a max redirection counter
- // to avoid bouncing between 2 or more urls
- let fetch_future = loop_fn((client, url), |(client, url)| {
- client
- .get(url.clone())
- .map_err(DenoError::from)
- .and_then(move |response| {
- if response.status().is_redirection() {
- let location_string = response
- .headers()
- .get("location")
- .expect("url redirection should provide 'location' header")
- .to_str()
- .unwrap()
- .to_string();
- debug!("Redirecting to {}...", &location_string);
- let new_url = resolve_uri_from_location(&url, &location_string);
- return Ok(Loop::Continue((client, new_url)));
- }
- if !response.status().is_success() {
- return Err(errors::new(
- errors::ErrorKind::NotFound,
- "module not found".to_string(),
- ));
- }
- Ok(Loop::Break(response))
- })
- }).and_then(|response| {
- let content_type = response
- .headers()
- .get(CONTENT_TYPE)
- .map(|content_type| content_type.to_str().unwrap().to_string());
- let body = response
- .into_body()
- .concat2()
- .map(|body| String::from_utf8(body.to_vec()).unwrap())
- .map_err(DenoError::from);
- body.join(future::ok(content_type))
- }).and_then(|(body_string, maybe_content_type)| {
- future::ok((body_string, maybe_content_type.unwrap()))
- });
-
- tokio_util::block_on(fetch_future)
-}
-
-#[test]
-fn test_fetch_sync_string() {
- // Relies on external http server. See tools/http_server.py
- tokio_util::init(|| {
- let (p, m) =
- fetch_sync_string("http://127.0.0.1:4545/package.json").unwrap();
- println!("package.json len {}", p.len());
- assert!(p.len() > 1);
- assert!(m == "application/json")
- });
-}
-
-#[test]
-fn test_fetch_sync_string_with_redirect() {
- // Relies on external http server. See tools/http_server.py
- tokio_util::init(|| {
- let (p, m) =
- fetch_sync_string("http://127.0.0.1:4546/package.json").unwrap();
- println!("package.json len {}", p.len());
- assert!(p.len() > 1);
- assert!(m == "application/json")
- });
-}
-
-#[test]
-fn test_resolve_uri_from_location_full_1() {
- let url = "http://deno.land".parse::<Uri>().unwrap();
- let new_uri = resolve_uri_from_location(&url, "http://golang.org");
- assert_eq!(new_uri.host().unwrap(), "golang.org");
-}
-
-#[test]
-fn test_resolve_uri_from_location_full_2() {
- let url = "https://deno.land".parse::<Uri>().unwrap();
- let new_uri = resolve_uri_from_location(&url, "https://golang.org");
- assert_eq!(new_uri.host().unwrap(), "golang.org");
-}
-
-#[test]
-fn test_resolve_uri_from_location_relative_1() {
- let url = "http://deno.land/x".parse::<Uri>().unwrap();
- let new_uri = resolve_uri_from_location(&url, "//rust-lang.org/en-US");
- assert_eq!(new_uri.host().unwrap(), "rust-lang.org");
- assert_eq!(new_uri.path(), "/en-US");
-}
-
-#[test]
-fn test_resolve_uri_from_location_relative_2() {
- let url = "http://deno.land/x".parse::<Uri>().unwrap();
- let new_uri = resolve_uri_from_location(&url, "/y");
- assert_eq!(new_uri.host().unwrap(), "deno.land");
- assert_eq!(new_uri.path(), "/y");
-}
-
-#[test]
-fn test_resolve_uri_from_location_relative_3() {
- let url = "http://deno.land/x".parse::<Uri>().unwrap();
- let new_uri = resolve_uri_from_location(&url, "z");
- assert_eq!(new_uri.host().unwrap(), "deno.land");
- assert_eq!(new_uri.path(), "/x/z");
-}
diff --git a/src/isolate.rs b/src/isolate.rs
deleted file mode 100644
index 379203dd3..000000000
--- a/src/isolate.rs
+++ /dev/null
@@ -1,236 +0,0 @@
-// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-use crate::cli::Cli;
-use crate::compiler::compile_sync;
-use crate::compiler::ModuleMetaData;
-use crate::errors::DenoError;
-use crate::errors::RustOrJsError;
-use crate::isolate_state::IsolateState;
-use crate::js_errors;
-use crate::msg;
-use deno_core;
-use deno_core::deno_mod;
-use deno_core::JSError;
-use futures::Async;
-use futures::Future;
-use std::sync::Arc;
-
-type CoreIsolate = deno_core::Isolate<Cli>;
-
-/// Wraps deno_core::Isolate to provide source maps, ops for the CLI, and
-/// high-level module loading
-pub struct Isolate {
- inner: CoreIsolate,
- state: Arc<IsolateState>,
-}
-
-impl Isolate {
- pub fn new(cli: Cli) -> Isolate {
- let state = cli.state.clone();
- Self {
- inner: CoreIsolate::new(cli),
- state,
- }
- }
-
- /// Same as execute2() but the filename defaults to "<anonymous>".
- pub fn execute(&mut self, js_source: &str) -> Result<(), JSError> {
- self.execute2("<anonymous>", js_source)
- }
-
- /// Executes the provided JavaScript source code. The js_filename argument is
- /// provided only for debugging purposes.
- pub fn execute2(
- &mut self,
- js_filename: &str,
- js_source: &str,
- ) -> Result<(), JSError> {
- self.inner.execute(js_filename, js_source)
- }
-
- // TODO(ry) make this return a future.
- fn mod_load_deps(&self, id: deno_mod) -> Result<(), RustOrJsError> {
- // basically iterate over the imports, start loading them.
-
- let referrer_name = {
- let g = self.state.modules.lock().unwrap();
- g.get_name(id).unwrap().clone()
- };
-
- for specifier in self.inner.mod_get_imports(id) {
- let (name, _local_filename) = self
- .state
- .dir
- .resolve_module(&specifier, &referrer_name)
- .map_err(DenoError::from)
- .map_err(RustOrJsError::from)?;
-
- debug!("mod_load_deps {}", name);
-
- if !self.state.modules.lock().unwrap().is_registered(&name) {
- let out = fetch_module_meta_data_and_maybe_compile(
- &self.state,
- &specifier,
- &referrer_name,
- )?;
- let child_id = self.mod_new_and_register(
- false,
- &out.module_name.clone(),
- &out.js_source(),
- )?;
-
- self.mod_load_deps(child_id)?;
- }
- }
-
- Ok(())
- }
-
- /// Executes the provided JavaScript module.
- pub fn execute_mod(
- &mut self,
- js_filename: &str,
- is_prefetch: bool,
- ) -> Result<(), RustOrJsError> {
- // TODO move isolate_state::execute_mod impl here.
- self
- .execute_mod_inner(js_filename, is_prefetch)
- .map_err(|err| match err {
- RustOrJsError::Js(err) => RustOrJsError::Js(self.apply_source_map(err)),
- x => x,
- })
- }
-
- /// High-level way to execute modules.
- /// This will issue HTTP requests and file system calls.
- /// Blocks. TODO(ry) Don't block.
- fn execute_mod_inner(
- &mut self,
- url: &str,
- is_prefetch: bool,
- ) -> Result<(), RustOrJsError> {
- let out = fetch_module_meta_data_and_maybe_compile(&self.state, url, ".")
- .map_err(RustOrJsError::from)?;
-
- let id = self
- .mod_new_and_register(true, &out.module_name.clone(), &out.js_source())
- .map_err(RustOrJsError::from)?;
-
- self.mod_load_deps(id)?;
-
- self
- .inner
- .mod_instantiate(id)
- .map_err(RustOrJsError::from)?;
- if !is_prefetch {
- self.inner.mod_evaluate(id).map_err(RustOrJsError::from)?;
- }
- Ok(())
- }
-
- /// Wraps Isolate::mod_new but registers with modules.
- fn mod_new_and_register(
- &self,
- main: bool,
- name: &str,
- source: &str,
- ) -> Result<deno_mod, JSError> {
- let id = self.inner.mod_new(main, name, source)?;
- self.state.modules.lock().unwrap().register(id, &name);
- Ok(id)
- }
-
- pub fn print_file_info(&self, module: &str) {
- let m = self.state.modules.lock().unwrap();
- m.print_file_info(&self.state.dir, module.to_string());
- }
-
- /// Applies source map to the error.
- fn apply_source_map(&self, err: JSError) -> JSError {
- js_errors::apply_source_map(&err, &self.state.dir)
- }
-}
-
-impl Future for Isolate {
- type Item = ();
- type Error = JSError;
-
- fn poll(&mut self) -> Result<Async<()>, Self::Error> {
- self.inner.poll().map_err(|err| self.apply_source_map(err))
- }
-}
-
-fn fetch_module_meta_data_and_maybe_compile(
- state: &Arc<IsolateState>,
- specifier: &str,
- referrer: &str,
-) -> Result<ModuleMetaData, DenoError> {
- let mut out = state.dir.fetch_module_meta_data(specifier, referrer)?;
- if (out.media_type == msg::MediaType::TypeScript
- && out.maybe_output_code.is_none())
- || state.flags.recompile
- {
- debug!(">>>>> compile_sync START");
- out = compile_sync(state, specifier, &referrer, &out);
- debug!(">>>>> compile_sync END");
- state.dir.code_cache(&out)?;
- }
- Ok(out)
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use crate::flags;
- use crate::permissions::DenoPermissions;
- use crate::tokio_util;
- use futures::future::lazy;
- use std::sync::atomic::Ordering;
-
- #[test]
- fn execute_mod() {
- let filename = std::env::current_dir()
- .unwrap()
- .join("tests/esm_imports_a.js");
- let filename = filename.to_str().unwrap().to_string();
-
- let argv = vec![String::from("./deno"), filename.clone()];
- let (flags, rest_argv, _) = flags::set_flags(argv).unwrap();
-
- let state = Arc::new(IsolateState::new(flags, rest_argv, None));
- let state_ = state.clone();
- tokio_util::run(lazy(move || {
- let cli = Cli::new(None, state.clone(), DenoPermissions::default());
- let mut isolate = Isolate::new(cli);
- if let Err(err) = isolate.execute_mod(&filename, false) {
- eprintln!("execute_mod err {:?}", err);
- }
- tokio_util::panic_on_error(isolate)
- }));
-
- let metrics = &state_.metrics;
- assert_eq!(metrics.resolve_count.load(Ordering::SeqCst), 1);
- }
-
- #[test]
- fn execute_mod_circular() {
- let filename = std::env::current_dir().unwrap().join("tests/circular1.js");
- let filename = filename.to_str().unwrap().to_string();
-
- let argv = vec![String::from("./deno"), filename.clone()];
- let (flags, rest_argv, _) = flags::set_flags(argv).unwrap();
-
- let state = Arc::new(IsolateState::new(flags, rest_argv, None));
- let state_ = state.clone();
- tokio_util::run(lazy(move || {
- let cli = Cli::new(None, state.clone(), DenoPermissions::default());
- let mut isolate = Isolate::new(cli);
- if let Err(err) = isolate.execute_mod(&filename, false) {
- eprintln!("execute_mod err {:?}", err);
- }
- tokio_util::panic_on_error(isolate)
- }));
-
- let metrics = &state_.metrics;
- assert_eq!(metrics.resolve_count.load(Ordering::SeqCst), 2);
- }
-}
diff --git a/src/isolate_state.rs b/src/isolate_state.rs
deleted file mode 100644
index 4cc010389..000000000
--- a/src/isolate_state.rs
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-use crate::cli::Buf;
-use crate::deno_dir;
-use crate::flags;
-use crate::global_timer::GlobalTimer;
-use crate::modules::Modules;
-use futures::sync::mpsc as async_mpsc;
-use std;
-use std::env;
-use std::sync::atomic::{AtomicUsize, Ordering};
-use std::sync::Mutex;
-
-pub type WorkerSender = async_mpsc::Sender<Buf>;
-pub type WorkerReceiver = async_mpsc::Receiver<Buf>;
-pub type WorkerChannels = (WorkerSender, WorkerReceiver);
-
-// AtomicU64 is currently unstable
-#[derive(Default)]
-pub struct Metrics {
- pub ops_dispatched: AtomicUsize,
- pub ops_completed: AtomicUsize,
- pub bytes_sent_control: AtomicUsize,
- pub bytes_sent_data: AtomicUsize,
- pub bytes_received: AtomicUsize,
- pub resolve_count: AtomicUsize,
-}
-
-// Isolate cannot be passed between threads but IsolateState can.
-// IsolateState satisfies Send and Sync.
-// So any state that needs to be accessed outside the main V8 thread should be
-// inside IsolateState.
-#[cfg_attr(feature = "cargo-clippy", allow(stutter))]
-pub struct IsolateState {
- pub dir: deno_dir::DenoDir,
- pub argv: Vec<String>,
- pub flags: flags::DenoFlags,
- pub metrics: Metrics,
- pub modules: Mutex<Modules>,
- pub worker_channels: Option<Mutex<WorkerChannels>>,
- pub global_timer: Mutex<GlobalTimer>,
-}
-
-impl IsolateState {
- pub fn new(
- flags: flags::DenoFlags,
- argv_rest: Vec<String>,
- worker_channels: Option<WorkerChannels>,
- ) -> Self {
- let custom_root = env::var("DENO_DIR").map(|s| s.into()).ok();
-
- Self {
- dir: deno_dir::DenoDir::new(flags.reload, flags.recompile, custom_root)
- .unwrap(),
- argv: argv_rest,
- flags,
- metrics: Metrics::default(),
- modules: Mutex::new(Modules::new()),
- worker_channels: worker_channels.map(Mutex::new),
- global_timer: Mutex::new(GlobalTimer::new()),
- }
- }
-
- pub fn main_module(&self) -> Option<String> {
- if self.argv.len() <= 1 {
- None
- } else {
- let specifier = self.argv[1].clone();
- let referrer = ".";
- match self.dir.resolve_module_url(&specifier, referrer) {
- Ok(url) => Some(url.to_string()),
- Err(e) => {
- debug!("Potentially swallowed error {}", e);
- None
- }
- }
- }
- }
-
- #[cfg(test)]
- pub fn mock() -> IsolateState {
- let argv = vec![String::from("./deno"), String::from("hello.js")];
- // For debugging: argv.push_back(String::from("-D"));
- let (flags, rest_argv, _) = flags::set_flags(argv).unwrap();
- IsolateState::new(flags, rest_argv, None)
- }
-
- pub fn metrics_op_dispatched(
- &self,
- bytes_sent_control: usize,
- bytes_sent_data: usize,
- ) {
- self.metrics.ops_dispatched.fetch_add(1, Ordering::SeqCst);
- self
- .metrics
- .bytes_sent_control
- .fetch_add(bytes_sent_control, Ordering::SeqCst);
- self
- .metrics
- .bytes_sent_data
- .fetch_add(bytes_sent_data, Ordering::SeqCst);
- }
-
- pub fn metrics_op_completed(&self, bytes_received: usize) {
- self.metrics.ops_completed.fetch_add(1, Ordering::SeqCst);
- self
- .metrics
- .bytes_received
- .fetch_add(bytes_received, Ordering::SeqCst);
- }
-}
diff --git a/src/js_errors.rs b/src/js_errors.rs
deleted file mode 100644
index 90c9f2007..000000000
--- a/src/js_errors.rs
+++ /dev/null
@@ -1,424 +0,0 @@
-// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-//! This mod adds source maps and ANSI color display to deno_core::JSError.
-use crate::ansi;
-use deno_core::JSError;
-use deno_core::StackFrame;
-use source_map_mappings::parse_mappings;
-use source_map_mappings::Bias;
-use source_map_mappings::Mappings;
-use std::collections::HashMap;
-use std::fmt;
-use std::str;
-
-/// Wrapper around JSError which provides color to_string.
-pub struct JSErrorColor<'a>(pub &'a JSError);
-
-struct StackFrameColor<'a>(&'a StackFrame);
-
-pub trait SourceMapGetter {
- /// Returns the raw source map file.
- fn get_source_map(&self, script_name: &str) -> Option<Vec<u8>>;
-}
-
-/// Cached filename lookups. The key can be None if a previous lookup failed to
-/// find a SourceMap.
-type CachedMaps = HashMap<String, Option<SourceMap>>;
-
-struct SourceMap {
- mappings: Mappings,
- sources: Vec<String>,
-}
-
-impl<'a> fmt::Display for StackFrameColor<'a> {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let frame = self.0;
- // Note when we print to string, we change from 0-indexed to 1-indexed.
- let function_name = ansi::italic_bold(frame.function_name.clone());
- let script_line_column =
- format_script_line_column(&frame.script_name, frame.line, frame.column);
-
- if !frame.function_name.is_empty() {
- write!(f, " at {} ({})", function_name, script_line_column)
- } else if frame.is_eval {
- write!(f, " at eval ({})", script_line_column)
- } else {
- write!(f, " at {}", script_line_column)
- }
- }
-}
-
-fn format_script_line_column(
- script_name: &str,
- line: i64,
- column: i64,
-) -> String {
- // TODO match this style with how typescript displays errors.
- let line = ansi::yellow((1 + line).to_string());
- let column = ansi::yellow((1 + column).to_string());
- let script_name = ansi::cyan(script_name.to_string());
- format!("{}:{}:{}", script_name, line, column)
-}
-
-impl<'a> fmt::Display for JSErrorColor<'a> {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let e = self.0;
- if e.script_resource_name.is_some() {
- let script_resource_name = e.script_resource_name.as_ref().unwrap();
- // Avoid showing internal code from gen/bundle/main.js
- if script_resource_name != "gen/bundle/main.js"
- && script_resource_name != "gen/bundle/compiler.js"
- {
- if e.line_number.is_some() && e.start_column.is_some() {
- assert!(e.line_number.is_some());
- assert!(e.start_column.is_some());
- let script_line_column = format_script_line_column(
- script_resource_name,
- e.line_number.unwrap() - 1,
- e.start_column.unwrap() - 1,
- );
- write!(f, "{}", script_line_column)?;
- }
- if e.source_line.is_some() {
- write!(f, "\n{}\n", e.source_line.as_ref().unwrap())?;
- let mut s = String::new();
- for i in 0..e.end_column.unwrap() {
- if i >= e.start_column.unwrap() {
- s.push('^');
- } else {
- s.push(' ');
- }
- }
- writeln!(f, "{}", ansi::red_bold(s))?;
- }
- }
- }
-
- write!(f, "{}", ansi::bold(e.message.clone()))?;
-
- for frame in &e.frames {
- write!(f, "\n{}", StackFrameColor(&frame).to_string())?;
- }
- Ok(())
- }
-}
-
-impl SourceMap {
- fn from_json(json_str: &str) -> Option<Self> {
- // Ugly. Maybe use serde_derive.
- match serde_json::from_str::<serde_json::Value>(json_str) {
- Ok(serde_json::Value::Object(map)) => match map["mappings"].as_str() {
- None => None,
- Some(mappings_str) => {
- match parse_mappings::<()>(mappings_str.as_bytes()) {
- Err(_) => None,
- Ok(mappings) => {
- if !map["sources"].is_array() {
- return None;
- }
- let sources_val = map["sources"].as_array().unwrap();
- let mut sources = Vec::<String>::new();
-
- for source_val in sources_val {
- match source_val.as_str() {
- None => return None,
- Some(source) => {
- sources.push(source.to_string());
- }
- }
- }
-
- Some(SourceMap { sources, mappings })
- }
- }
- }
- },
- _ => None,
- }
- }
-}
-
-fn frame_apply_source_map(
- frame: &StackFrame,
- mappings_map: &mut CachedMaps,
- getter: &dyn SourceMapGetter,
-) -> StackFrame {
- let maybe_sm = get_mappings(frame.script_name.as_ref(), mappings_map, getter);
- let frame_pos = (
- frame.script_name.to_owned(),
- frame.line as i64,
- frame.column as i64,
- );
- let (script_name, line, column) = match maybe_sm {
- None => frame_pos,
- Some(sm) => match sm.mappings.original_location_for(
- frame.line as u32,
- frame.column as u32,
- Bias::default(),
- ) {
- None => frame_pos,
- Some(mapping) => match &mapping.original {
- None => frame_pos,
- Some(original) => {
- let orig_source = sm.sources[original.source as usize].clone();
- (
- orig_source,
- i64::from(original.original_line),
- i64::from(original.original_column),
- )
- }
- },
- },
- };
-
- StackFrame {
- script_name,
- function_name: frame.function_name.clone(),
- line,
- column,
- is_eval: frame.is_eval,
- is_constructor: frame.is_constructor,
- is_wasm: frame.is_wasm,
- }
-}
-
-pub fn apply_source_map(
- js_error: &JSError,
- getter: &dyn SourceMapGetter,
-) -> JSError {
- let mut mappings_map: CachedMaps = HashMap::new();
- let mut frames = Vec::<StackFrame>::new();
- for frame in &js_error.frames {
- let f = frame_apply_source_map(&frame, &mut mappings_map, getter);
- frames.push(f);
- }
- JSError {
- message: js_error.message.clone(),
- frames,
- error_level: js_error.error_level,
- source_line: js_error.source_line.clone(),
- // TODO the following need to be source mapped:
- script_resource_name: js_error.script_resource_name.clone(),
- line_number: js_error.line_number,
- start_position: js_error.start_position,
- end_position: js_error.end_position,
- start_column: js_error.start_column,
- end_column: js_error.end_column,
- }
-}
-
-// The bundle does not get built for 'cargo check', so we don't embed the
-// bundle source map.
-#[cfg(feature = "check-only")]
-fn builtin_source_map(script_name: &str) -> Option<Vec<u8>> {
- None
-}
-
-#[cfg(not(feature = "check-only"))]
-fn builtin_source_map(script_name: &str) -> Option<Vec<u8>> {
- match script_name {
- "gen/bundle/main.js" => Some(
- include_bytes!(concat!(env!("GN_OUT_DIR"), "/gen/bundle/main.js.map"))
- .to_vec(),
- ),
- "gen/bundle/compiler.js" => Some(
- include_bytes!(concat!(
- env!("GN_OUT_DIR"),
- "/gen/bundle/compiler.js.map"
- )).to_vec(),
- ),
- _ => None,
- }
-}
-
-fn parse_map_string(
- script_name: &str,
- getter: &dyn SourceMapGetter,
-) -> Option<SourceMap> {
- builtin_source_map(script_name)
- .or_else(|| getter.get_source_map(script_name))
- .and_then(|raw_source_map| {
- SourceMap::from_json(str::from_utf8(&raw_source_map).unwrap())
- })
-}
-
-fn get_mappings<'a>(
- script_name: &str,
- mappings_map: &'a mut CachedMaps,
- getter: &dyn SourceMapGetter,
-) -> &'a Option<SourceMap> {
- mappings_map
- .entry(script_name.to_string())
- .or_insert_with(|| parse_map_string(script_name, getter))
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use crate::ansi::strip_ansi_codes;
-
- fn error1() -> JSError {
- JSError {
- message: "Error: foo bar".to_string(),
- source_line: None,
- script_resource_name: None,
- line_number: None,
- start_position: None,
- end_position: None,
- error_level: None,
- start_column: None,
- end_column: None,
- frames: vec![
- StackFrame {
- line: 4,
- column: 16,
- script_name: "foo_bar.ts".to_string(),
- function_name: "foo".to_string(),
- is_eval: false,
- is_constructor: false,
- is_wasm: false,
- },
- StackFrame {
- line: 5,
- column: 20,
- script_name: "bar_baz.ts".to_string(),
- function_name: "qat".to_string(),
- is_eval: false,
- is_constructor: false,
- is_wasm: false,
- },
- StackFrame {
- line: 1,
- column: 1,
- script_name: "deno_main.js".to_string(),
- function_name: "".to_string(),
- is_eval: false,
- is_constructor: false,
- is_wasm: false,
- },
- ],
- }
- }
-
- struct MockSourceMapGetter {}
-
- impl SourceMapGetter for MockSourceMapGetter {
- fn get_source_map(&self, script_name: &str) -> Option<Vec<u8>> {
- let s = match script_name {
- "foo_bar.ts" => r#"{"sources": ["foo_bar.ts"], "mappings":";;;IAIA,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC;IAC/C,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAE3C,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC"}"#,
- "bar_baz.ts" => r#"{"sources": ["bar_baz.ts"], "mappings":";;;IAEA,CAAC,KAAK,IAAI,EAAE;QACV,MAAM,GAAG,GAAG,sDAAa,OAAO,2BAAC,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC,CAAC,EAAE,CAAC;IAEQ,QAAA,GAAG,GAAG,KAAK,CAAC;IAEzB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC"}"#,
- _ => return None,
- };
- Some(s.as_bytes().to_owned())
- }
- }
-
- #[test]
- fn js_error_to_string() {
- let e = error1();
- assert_eq!("Error: foo bar\n at foo (foo_bar.ts:5:17)\n at qat (bar_baz.ts:6:21)\n at deno_main.js:2:2", strip_ansi_codes(&e.to_string()));
- }
-
- #[test]
- fn js_error_apply_source_map_1() {
- let e = error1();
- let getter = MockSourceMapGetter {};
- let actual = apply_source_map(&e, &getter);
- let expected = JSError {
- message: "Error: foo bar".to_string(),
- source_line: None,
- script_resource_name: None,
- line_number: None,
- start_position: None,
- end_position: None,
- error_level: None,
- start_column: None,
- end_column: None,
- frames: vec![
- StackFrame {
- line: 5,
- column: 12,
- script_name: "foo_bar.ts".to_string(),
- function_name: "foo".to_string(),
- is_eval: false,
- is_constructor: false,
- is_wasm: false,
- },
- StackFrame {
- line: 4,
- column: 14,
- script_name: "bar_baz.ts".to_string(),
- function_name: "qat".to_string(),
- is_eval: false,
- is_constructor: false,
- is_wasm: false,
- },
- StackFrame {
- line: 1,
- column: 1,
- script_name: "deno_main.js".to_string(),
- function_name: "".to_string(),
- is_eval: false,
- is_constructor: false,
- is_wasm: false,
- },
- ],
- };
- assert_eq!(actual, expected);
- }
-
- #[test]
- fn js_error_apply_source_map_2() {
- let e = JSError {
- message: "TypeError: baz".to_string(),
- source_line: None,
- script_resource_name: None,
- line_number: None,
- start_position: None,
- end_position: None,
- error_level: None,
- start_column: None,
- end_column: None,
- frames: vec![StackFrame {
- line: 11,
- column: 12,
- script_name: "gen/bundle/main.js".to_string(),
- function_name: "setLogDebug".to_string(),
- is_eval: false,
- is_constructor: false,
- is_wasm: false,
- }],
- };
- let getter = MockSourceMapGetter {};
- let actual = apply_source_map(&e, &getter);
- assert_eq!(actual.message, "TypeError: baz");
- // Because this is accessing the live bundle, this test might be more fragile
- assert_eq!(actual.frames.len(), 1);
- assert!(actual.frames[0].script_name.ends_with("js/util.ts"));
- }
-
- #[test]
- fn source_map_from_json() {
- let json = r#"{"version":3,"file":"error_001.js","sourceRoot":"","sources":["file:///Users/rld/src/deno/tests/error_001.ts"],"names":[],"mappings":"AAAA,SAAS,GAAG;IACV,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC;AACrB,CAAC;AAED,SAAS,GAAG;IACV,GAAG,EAAE,CAAC;AACR,CAAC;AAED,GAAG,EAAE,CAAC"}"#;
- let sm = SourceMap::from_json(json).unwrap();
- assert_eq!(sm.sources.len(), 1);
- assert_eq!(
- sm.sources[0],
- "file:///Users/rld/src/deno/tests/error_001.ts"
- );
- let mapping = sm
- .mappings
- .original_location_for(1, 10, Bias::default())
- .unwrap();
- assert_eq!(mapping.generated_line, 1);
- assert_eq!(mapping.generated_column, 10);
- assert_eq!(
- mapping.original,
- Some(source_map_mappings::OriginalLocation {
- source: 0,
- original_line: 1,
- original_column: 8,
- name: None
- })
- );
- }
-}
diff --git a/src/main.rs b/src/main.rs
deleted file mode 100644
index 4657a3a4d..000000000
--- a/src/main.rs
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-#[macro_use]
-extern crate lazy_static;
-#[macro_use]
-extern crate log;
-#[macro_use]
-extern crate futures;
-#[macro_use]
-extern crate serde_json;
-
-mod ansi;
-pub mod cli;
-pub mod compiler;
-pub mod deno_dir;
-pub mod errors;
-pub mod flags;
-mod fs;
-mod global_timer;
-mod http_body;
-mod http_util;
-pub mod isolate;
-pub mod isolate_state;
-pub mod js_errors;
-pub mod modules;
-pub mod msg;
-pub mod msg_util;
-pub mod ops;
-pub mod permissions;
-mod repl;
-pub mod resolve_addr;
-pub mod resources;
-mod startup_data;
-mod tokio_util;
-mod tokio_write;
-pub mod version;
-pub mod workers;
-
-use crate::cli::Cli;
-use crate::errors::RustOrJsError;
-use crate::isolate::Isolate;
-use crate::isolate_state::IsolateState;
-use futures::lazy;
-use futures::Future;
-use log::{LevelFilter, Metadata, Record};
-use std::env;
-use std::sync::Arc;
-
-static LOGGER: Logger = Logger;
-
-struct Logger;
-
-impl log::Log for Logger {
- fn enabled(&self, metadata: &Metadata) -> bool {
- metadata.level() <= log::max_level()
- }
-
- fn log(&self, record: &Record) {
- if self.enabled(record.metadata()) {
- println!("{} RS - {}", record.level(), record.args());
- }
- }
- fn flush(&self) {}
-}
-
-fn print_err_and_exit(err: RustOrJsError) {
- eprintln!("{}", err.to_string());
- std::process::exit(1);
-}
-
-fn js_check<E>(r: Result<(), E>)
-where
- E: Into<RustOrJsError>,
-{
- if let Err(err) = r {
- print_err_and_exit(err.into());
- }
-}
-
-fn main() {
- #[cfg(windows)]
- ansi_term::enable_ansi_support().ok(); // For Windows 10
-
- log::set_logger(&LOGGER).unwrap();
- let args = env::args().collect();
- let (mut flags, mut rest_argv, usage_string) = flags::set_flags(args)
- .unwrap_or_else(|err| {
- eprintln!("{}", err);
- std::process::exit(1)
- });
-
- if flags.help {
- println!("{}", &usage_string);
- std::process::exit(0);
- }
-
- log::set_max_level(if flags.log_debug {
- LevelFilter::Debug
- } else {
- LevelFilter::Warn
- });
-
- if flags.fmt {
- rest_argv.insert(1, "https://deno.land/std/prettier/main.ts".to_string());
- flags.allow_read = true;
- flags.allow_write = true;
- }
-
- let should_prefetch = flags.prefetch || flags.info;
- let should_display_info = flags.info;
-
- let state = Arc::new(IsolateState::new(flags, rest_argv, None));
- let state_ = state.clone();
- let startup_data = startup_data::deno_isolate_init();
- let permissions = permissions::DenoPermissions::from_flags(&state.flags);
- let cli = Cli::new(Some(startup_data), state_, permissions);
- let mut isolate = Isolate::new(cli);
-
- let main_future = lazy(move || {
- // Setup runtime.
- js_check(isolate.execute("denoMain()"));
-
- // Execute main module.
- if let Some(main_module) = state.main_module() {
- debug!("main_module {}", main_module);
- js_check(isolate.execute_mod(&main_module, should_prefetch));
- if should_display_info {
- // Display file info and exit. Do not run file
- isolate.print_file_info(&main_module);
- std::process::exit(0);
- }
- }
-
- isolate.then(|result| {
- js_check(result);
- Ok(())
- })
- });
-
- tokio_util::run(main_future);
-}
diff --git a/src/modules.rs b/src/modules.rs
deleted file mode 100644
index 908c31b6d..000000000
--- a/src/modules.rs
+++ /dev/null
@@ -1,204 +0,0 @@
-// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-use crate::ansi;
-use crate::deno_dir::DenoDir;
-use crate::msg;
-use deno_core::deno_mod;
-use std::collections::HashMap;
-use std::collections::HashSet;
-use std::fmt;
-
-pub struct ModuleInfo {
- name: String,
- children: Vec<deno_mod>,
-}
-
-/// A collection of JS modules.
-#[derive(Default)]
-pub struct Modules {
- pub info: HashMap<deno_mod, ModuleInfo>,
- pub by_name: HashMap<String, deno_mod>,
-}
-
-impl Modules {
- pub fn new() -> Modules {
- Self {
- info: HashMap::new(),
- by_name: HashMap::new(),
- }
- }
-
- pub fn get_id(&self, name: &str) -> Option<deno_mod> {
- self.by_name.get(name).cloned()
- }
-
- pub fn get_children(&self, id: deno_mod) -> Option<&Vec<deno_mod>> {
- self.info.get(&id).map(|i| &i.children)
- }
-
- pub fn get_name(&self, id: deno_mod) -> Option<&String> {
- self.info.get(&id).map(|i| &i.name)
- }
-
- pub fn is_registered(&self, name: &str) -> bool {
- self.by_name.get(name).is_some()
- }
-
- pub fn register(&mut self, id: deno_mod, name: &str) {
- let name = String::from(name);
- debug!("register {}", name);
- self.by_name.insert(name.clone(), id);
- self.info.insert(
- id,
- ModuleInfo {
- name,
- children: Vec::new(),
- },
- );
- }
-
- pub fn resolve_cb(
- &mut self,
- deno_dir: &DenoDir,
- specifier: &str,
- referrer: deno_mod,
- ) -> deno_mod {
- debug!("resolve_cb {}", specifier);
-
- let maybe_info = self.info.get_mut(&referrer);
- if maybe_info.is_none() {
- debug!("cant find referrer {}", referrer);
- return 0;
- }
- let info = maybe_info.unwrap();
- let referrer_name = &info.name;
- let r = deno_dir.resolve_module(specifier, referrer_name);
- if let Err(err) = r {
- debug!("potentially swallowed err: {}", err);
- return 0;
- }
- let (name, _local_filename) = r.unwrap();
-
- if let Some(id) = self.by_name.get(&name) {
- let child_id = *id;
- info.children.push(child_id);
- return child_id;
- } else {
- return 0;
- }
- }
-
- pub fn print_file_info(&self, deno_dir: &DenoDir, filename: String) {
- let maybe_out = deno_dir.fetch_module_meta_data(&filename, ".");
- if maybe_out.is_err() {
- println!("{}", maybe_out.unwrap_err());
- return;
- }
- let out = maybe_out.unwrap();
-
- println!("{} {}", ansi::bold("local:".to_string()), &(out.filename));
- println!(
- "{} {}",
- ansi::bold("type:".to_string()),
- msg::enum_name_media_type(out.media_type)
- );
- if out.maybe_output_code_filename.is_some() {
- println!(
- "{} {}",
- ansi::bold("compiled:".to_string()),
- out.maybe_output_code_filename.as_ref().unwrap(),
- );
- }
- if out.maybe_source_map_filename.is_some() {
- println!(
- "{} {}",
- ansi::bold("map:".to_string()),
- out.maybe_source_map_filename.as_ref().unwrap()
- );
- }
-
- let deps = Deps::new(self, &out.module_name);
- println!("{}{}", ansi::bold("deps:\n".to_string()), deps.name);
- if let Some(ref depsdeps) = deps.deps {
- for d in depsdeps {
- println!("{}", d);
- }
- }
- }
-}
-
-pub struct Deps {
- pub name: String,
- pub deps: Option<Vec<Deps>>,
- prefix: String,
- is_last: bool,
-}
-
-impl Deps {
- pub fn new(modules: &Modules, module_name: &str) -> Deps {
- let mut seen = HashSet::new();
- let id = modules.get_id(module_name).unwrap();
- Self::helper(&mut seen, "".to_string(), true, modules, id)
- }
-
- fn helper(
- seen: &mut HashSet<deno_mod>,
- prefix: String,
- is_last: bool,
- modules: &Modules,
- id: deno_mod,
- ) -> Deps {
- let name = modules.get_name(id).unwrap().to_string();
- if seen.contains(&id) {
- Deps {
- name,
- prefix,
- deps: None,
- is_last,
- }
- } else {
- seen.insert(id);
- let child_ids = modules.get_children(id).unwrap();
- let child_count = child_ids.iter().count();
- let deps = child_ids
- .iter()
- .enumerate()
- .map(|(index, dep_id)| {
- let new_is_last = index == child_count - 1;
- let mut new_prefix = prefix.clone();
- new_prefix.push(if is_last { ' ' } else { '│' });
- new_prefix.push(' ');
- Self::helper(seen, new_prefix, new_is_last, modules, *dep_id)
- }).collect();
- Deps {
- name,
- prefix,
- deps: Some(deps),
- is_last,
- }
- }
- }
-}
-
-impl fmt::Display for Deps {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let mut has_children = false;
- if let Some(ref deps) = self.deps {
- has_children = !deps.is_empty();
- }
- write!(
- f,
- "{}{}─{} {}",
- self.prefix,
- if self.is_last { "└" } else { "├" },
- if has_children { "┬" } else { "─" },
- self.name
- )?;
-
- if let Some(ref deps) = self.deps {
- for d in deps {
- write!(f, "\n{}", d)?;
- }
- }
- Ok(())
- }
-}
diff --git a/src/msg.fbs b/src/msg.fbs
deleted file mode 100644
index 243034cfb..000000000
--- a/src/msg.fbs
+++ /dev/null
@@ -1,524 +0,0 @@
-union Any {
- Accept,
- Chdir,
- Chmod,
- Close,
- CopyFile,
- Cwd,
- CwdRes,
- Dial,
- Environ,
- EnvironRes,
- Exit,
- Fetch,
- FetchModuleMetaData,
- FetchModuleMetaDataRes,
- FetchRes,
- FormatError,
- FormatErrorRes,
- GlobalTimer,
- GlobalTimerRes,
- GlobalTimerStop,
- IsTTY,
- IsTTYRes,
- Listen,
- ListenRes,
- MakeTempDir,
- MakeTempDirRes,
- Metrics,
- MetricsRes,
- Mkdir,
- NewConn,
- Now,
- NowRes,
- Open,
- OpenRes,
- PermissionRevoke,
- Permissions,
- PermissionsRes,
- Read,
- ReadDir,
- ReadDirRes,
- ReadFile,
- ReadFileRes,
- ReadRes,
- Readlink,
- ReadlinkRes,
- Remove,
- Rename,
- ReplReadline,
- ReplReadlineRes,
- ReplStart,
- ReplStartRes,
- Resources,
- ResourcesRes,
- Run,
- RunRes,
- RunStatus,
- RunStatusRes,
- Seek,
- SetEnv,
- Shutdown,
- Start,
- StartRes,
- Stat,
- StatRes,
- Symlink,
- Truncate,
- WorkerGetMessage,
- WorkerGetMessageRes,
- WorkerPostMessage,
- Write,
- WriteFile,
- WriteRes,
-}
-
-enum ErrorKind: byte {
- NoError = 0,
-
- // io errors
-
- NotFound,
- PermissionDenied,
- ConnectionRefused,
- ConnectionReset,
- ConnectionAborted,
- NotConnected,
- AddrInUse,
- AddrNotAvailable,
- BrokenPipe,
- AlreadyExists,
- WouldBlock,
- InvalidInput,
- InvalidData,
- TimedOut,
- Interrupted,
- WriteZero,
- Other,
- UnexpectedEof,
- BadResource,
- CommandFailed,
-
- // url errors
-
- EmptyHost,
- IdnaError,
- InvalidPort,
- InvalidIpv4Address,
- InvalidIpv6Address,
- InvalidDomainCharacter,
- RelativeUrlWithoutBase,
- RelativeUrlWithCannotBeABaseBase,
- SetHostOnCannotBeABaseUrl,
- Overflow,
-
- // hyper errors
-
- HttpUser,
- HttpClosed,
- HttpCanceled,
- HttpParse,
- HttpOther,
- TooLarge,
-
- // custom errors
- InvalidUri,
- InvalidSeekMode,
-}
-
-table Cwd {}
-
-table CwdRes {
- cwd: string;
-}
-
-enum MediaType: byte {
- JavaScript = 0,
- TypeScript,
- Json,
- Unknown
-}
-
-table Base {
- cmd_id: uint32;
- sync: bool = false;
- error_kind: ErrorKind = NoError;
- error: string;
- inner: Any;
-}
-
-table Start {
- unused: int8;
-}
-
-table StartRes {
- cwd: string;
- pid: uint32;
- argv: [string];
- exec_path: string;
- main_module: string; // Absolute URL.
- debug_flag: bool;
- deps_flag: bool;
- types_flag: bool;
- version_flag: bool;
- deno_version: string;
- v8_version: string;
- no_color: bool;
-}
-
-table FormatError {
- error: string;
-}
-
-table FormatErrorRes {
- error: string;
-}
-
-table WorkerGetMessage {
- unused: int8;
-}
-
-table WorkerGetMessageRes {
- data: [ubyte];
-}
-
-table WorkerPostMessage {
- // data passed thru the zero-copy data parameter.
-}
-
-table FetchModuleMetaData {
- specifier: string;
- referrer: string;
-}
-
-table FetchModuleMetaDataRes {
- // If it's a non-http module, moduleName and filename will be the same.
- // For http modules, moduleName is its resolved http URL, and filename
- // is the location of the locally downloaded source code.
- module_name: string;
- filename: string;
- media_type: MediaType;
- data: [ubyte];
-}
-
-table Chdir {
- directory: string;
-}
-
-table GlobalTimer {
- timeout: int;
-}
-
-table GlobalTimerRes { }
-
-table GlobalTimerStop { }
-
-table Exit {
- code: int;
-}
-
-table Environ {}
-
-table SetEnv {
- key: string;
- value: string;
-}
-
-table EnvironRes {
- map: [KeyValue];
-}
-
-table KeyValue {
- key: string;
- value: string;
-}
-
-table Permissions {}
-
-table PermissionRevoke {
- permission: string;
-}
-
-table PermissionsRes {
- run: bool;
- read: bool;
- write: bool;
- net: bool;
- env: bool;
-}
-
-// Note this represents The WHOLE header of an http message, not just the key
-// value pairs. That means it includes method and url for Requests and status
-// for responses. This is why it is singular "Header" instead of "Headers".
-table HttpHeader {
- is_request: bool;
- // Request only:
- method: string;
- url: string;
- // Response only:
- status: uint16;
- // Both:
- fields: [KeyValue];
-}
-
-table Fetch {
- header: HttpHeader;
-}
-
-table FetchRes {
- header: HttpHeader;
- body_rid: uint32;
-}
-
-table MakeTempDir {
- dir: string;
- prefix: string;
- suffix: string;
-}
-
-table MakeTempDirRes {
- path: string;
-}
-
-table Mkdir {
- path: string;
- recursive: bool;
- mode: uint; // Specified by https://godoc.org/os#FileMode
-}
-
-table Chmod {
- path: string;
- mode: uint; // Specified by https://godoc.org/os#FileMode
-}
-
-table Remove {
- path: string;
- recursive: bool;
-}
-
-table ReadFile {
- filename: string;
-}
-
-table ReadFileRes {
- data: [ubyte];
-}
-
-table ReadDir {
- path: string;
-}
-
-table ReadDirRes {
- entries: [StatRes];
-}
-
-table WriteFile {
- filename: string;
- data: [ubyte];
- update_perm: bool;
- perm: uint;
- // perm specified by https://godoc.org/os#FileMode
- is_create: bool;
- is_append: bool;
-}
-
-table CopyFile {
- from: string;
- to: string;
-}
-
-table Rename {
- oldpath: string;
- newpath: string;
-}
-
-table Readlink {
- name: string;
-}
-
-table ReadlinkRes {
- path: string;
-}
-
-table ReplStart {
- history_file: string;
- // TODO add config
-}
-
-table ReplStartRes {
- rid: uint32;
-}
-
-table ReplReadline {
- rid: uint32;
- prompt: string;
-}
-
-table ReplReadlineRes {
- line: string;
-}
-
-table Resources {}
-
-table Resource {
- rid: uint32;
- repr: string;
-}
-
-table ResourcesRes {
- resources: [Resource];
-}
-
-table Symlink {
- oldname: string;
- newname: string;
-}
-
-table Stat {
- filename: string;
- lstat: bool;
-}
-
-table StatRes {
- is_file: bool;
- is_symlink: bool;
- len: ulong;
- modified:ulong;
- accessed:ulong;
- created:ulong;
- mode: uint;
- has_mode: bool; // false on windows
- name: string;
- path: string;
-}
-
-table Truncate {
- name: string;
- len: uint;
-}
-
-table Open {
- filename: string;
- perm: uint;
- mode: string;
-}
-
-table OpenRes {
- rid: uint32;
-}
-
-table Read {
- rid: uint32;
- // (ptr, len) is passed as second parameter to libdeno.send().
-}
-
-table ReadRes {
- nread: uint;
- eof: bool;
-}
-
-table Write {
- rid: uint32;
-}
-
-table WriteRes {
- nbyte: uint;
-}
-
-table Close {
- rid: uint32;
-}
-
-table Shutdown {
- rid: uint32;
- how: uint;
-}
-
-table Listen {
- network: string;
- address: string;
-}
-
-table ListenRes {
- rid: uint32;
-}
-
-table Accept {
- rid: uint32;
-}
-
-table Dial {
- network: string;
- address: string;
-}
-
-// Response to Accept and Dial.
-table NewConn {
- rid: uint32;
- remote_addr: string;
- local_addr: string;
-}
-
-table Metrics {}
-
-table MetricsRes {
- ops_dispatched: uint64;
- ops_completed: uint64;
- bytes_sent_control: uint64;
- bytes_sent_data: uint64;
- bytes_received: uint64;
-}
-
-enum ProcessStdio: byte { Inherit, Piped, Null }
-
-table Run {
- args: [string];
- cwd: string;
- env: [KeyValue];
- stdin: ProcessStdio;
- stdout: ProcessStdio;
- stderr: ProcessStdio;
-}
-
-table RunRes {
- rid: uint32;
- pid: uint32;
- // The following stdio rids are only valid if "Piped" was specified for the
- // corresponding stdio stream. The caller MUST issue a close op for all valid
- // stdio streams.
- stdin_rid: uint32;
- stdout_rid: uint32;
- stderr_rid: uint32;
-}
-
-table RunStatus {
- rid: uint32;
-}
-
-table RunStatusRes {
- got_signal: bool;
- exit_code: int;
- exit_signal: int;
-}
-
-table Now {}
-
-table NowRes {
- time: uint64;
-}
-
-table IsTTY {}
-
-table IsTTYRes {
- stdin: bool;
- stdout: bool;
- stderr: bool;
-}
-
-table Seek {
- rid: uint32;
- offset: int;
- whence: uint;
-}
-
-root_type Base;
diff --git a/src/msg.rs b/src/msg.rs
deleted file mode 100644
index 080f39de8..000000000
--- a/src/msg.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-#![allow(unused_imports)]
-#![allow(dead_code)]
-#![cfg_attr(
- feature = "cargo-clippy",
- allow(clippy::all, clippy::pedantic)
-)]
-use crate::isolate_state;
-use flatbuffers;
-use std::sync::atomic::Ordering;
-
-// GN_OUT_DIR is set either by build.rs (for the Cargo build), or by
-// build_extra/rust/run.py (for the GN+Ninja build).
-include!(concat!(env!("GN_OUT_DIR"), "/gen/msg_generated.rs"));
-
-impl<'a> From<&'a isolate_state::Metrics> for MetricsResArgs {
- fn from(m: &'a isolate_state::Metrics) -> Self {
- MetricsResArgs {
- ops_dispatched: m.ops_dispatched.load(Ordering::SeqCst) as u64,
- ops_completed: m.ops_completed.load(Ordering::SeqCst) as u64,
- bytes_sent_control: m.bytes_sent_control.load(Ordering::SeqCst) as u64,
- bytes_sent_data: m.bytes_sent_data.load(Ordering::SeqCst) as u64,
- bytes_received: m.bytes_received.load(Ordering::SeqCst) as u64,
- }
- }
-}
diff --git a/src/msg_util.rs b/src/msg_util.rs
deleted file mode 100644
index 71bcc19d9..000000000
--- a/src/msg_util.rs
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-// Helpers for serialization.
-use crate::errors;
-use crate::errors::DenoResult;
-use crate::msg;
-
-use flatbuffers;
-use http::header::HeaderName;
-use http::uri::Uri;
-use http::Method;
-use hyper::header::HeaderMap;
-use hyper::header::HeaderValue;
-use hyper::Body;
-use hyper::Request;
-use hyper::Response;
-use std::str::FromStr;
-
-type Headers = HeaderMap<HeaderValue>;
-
-pub fn serialize_key_value<'bldr>(
- builder: &mut flatbuffers::FlatBufferBuilder<'bldr>,
- key: &str,
- value: &str,
-) -> flatbuffers::WIPOffset<msg::KeyValue<'bldr>> {
- let key = builder.create_string(&key);
- let value = builder.create_string(&value);
- msg::KeyValue::create(
- builder,
- &msg::KeyValueArgs {
- key: Some(key),
- value: Some(value),
- },
- )
-}
-
-pub fn serialize_request_header<'bldr>(
- builder: &mut flatbuffers::FlatBufferBuilder<'bldr>,
- r: &Request<Body>,
-) -> flatbuffers::WIPOffset<msg::HttpHeader<'bldr>> {
- let method = builder.create_string(r.method().as_str());
- let url = builder.create_string(r.uri().to_string().as_ref());
-
- let mut fields = Vec::new();
- for (key, val) in r.headers().iter() {
- let kv = serialize_key_value(builder, key.as_ref(), val.to_str().unwrap());
- fields.push(kv);
- }
- let fields = builder.create_vector(fields.as_ref());
-
- msg::HttpHeader::create(
- builder,
- &msg::HttpHeaderArgs {
- is_request: true,
- method: Some(method),
- url: Some(url),
- fields: Some(fields),
- ..Default::default()
- },
- )
-}
-
-pub fn serialize_fields<'bldr>(
- builder: &mut flatbuffers::FlatBufferBuilder<'bldr>,
- headers: &Headers,
-) -> flatbuffers::WIPOffset<
- flatbuffers::Vector<
- 'bldr,
- flatbuffers::ForwardsUOffset<msg::KeyValue<'bldr>>,
- >,
-> {
- let mut fields = Vec::new();
- for (key, val) in headers.iter() {
- let kv = serialize_key_value(builder, key.as_ref(), val.to_str().unwrap());
- fields.push(kv);
- }
- builder.create_vector(fields.as_ref())
-}
-
-// Not to be confused with serialize_response which has nothing to do with HTTP.
-pub fn serialize_http_response<'bldr>(
- builder: &mut flatbuffers::FlatBufferBuilder<'bldr>,
- r: &Response<Body>,
-) -> flatbuffers::WIPOffset<msg::HttpHeader<'bldr>> {
- let status = r.status().as_u16();
- let fields = serialize_fields(builder, r.headers());
- msg::HttpHeader::create(
- builder,
- &msg::HttpHeaderArgs {
- is_request: false,
- status,
- fields: Some(fields),
- ..Default::default()
- },
- )
-}
-
-pub fn deserialize_request(
- header_msg: msg::HttpHeader<'_>,
- body: Body,
-) -> DenoResult<Request<Body>> {
- let mut r = Request::new(body);
-
- assert!(header_msg.is_request());
-
- let u = header_msg.url().unwrap();
- let u = Uri::from_str(u)
- .map_err(|e| errors::new(msg::ErrorKind::InvalidUri, e.to_string()))?;
- *r.uri_mut() = u;
-
- if let Some(method) = header_msg.method() {
- let method = Method::from_str(method).unwrap();
- *r.method_mut() = method;
- }
-
- if let Some(fields) = header_msg.fields() {
- let headers = r.headers_mut();
- for i in 0..fields.len() {
- let kv = fields.get(i);
- let key = kv.key().unwrap();
- let name = HeaderName::from_bytes(key.as_bytes()).unwrap();
- let value = kv.value().unwrap();
- let v = HeaderValue::from_str(value).unwrap();
- headers.insert(name, v);
- }
- }
- Ok(r)
-}
diff --git a/src/ops.rs b/src/ops.rs
deleted file mode 100644
index 254a21563..000000000
--- a/src/ops.rs
+++ /dev/null
@@ -1,2020 +0,0 @@
-// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-use atty;
-use crate::ansi;
-use crate::cli::Buf;
-use crate::cli::Cli;
-use crate::errors;
-use crate::errors::{permission_denied, DenoError, DenoResult, ErrorKind};
-use crate::fs as deno_fs;
-use crate::http_util;
-use crate::isolate_state::IsolateState;
-use crate::js_errors::apply_source_map;
-use crate::js_errors::JSErrorColor;
-use crate::msg;
-use crate::msg_util;
-use crate::repl;
-use crate::resolve_addr::resolve_addr;
-use crate::resources;
-use crate::resources::table_entries;
-use crate::resources::Resource;
-use crate::tokio_util;
-use crate::tokio_write;
-use crate::version;
-use deno_core::deno_buf;
-use deno_core::JSError;
-use deno_core::Op;
-use flatbuffers::FlatBufferBuilder;
-use futures;
-use futures::Async;
-use futures::Poll;
-use futures::Sink;
-use futures::Stream;
-use hyper;
-use hyper::rt::Future;
-use remove_dir_all::remove_dir_all;
-use std;
-use std::convert::From;
-use std::fs;
-use std::net::Shutdown;
-use std::path::Path;
-use std::path::PathBuf;
-use std::process::Command;
-use std::sync::Arc;
-use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
-use tokio;
-use tokio::net::TcpListener;
-use tokio::net::TcpStream;
-use tokio_process::CommandExt;
-use tokio_threadpool;
-
-#[cfg(unix)]
-use std::os::unix::fs::PermissionsExt;
-#[cfg(unix)]
-use std::os::unix::process::ExitStatusExt;
-
-type OpResult = DenoResult<Buf>;
-
-pub type OpWithError = dyn Future<Item = Buf, Error = DenoError> + Send;
-
-// TODO Ideally we wouldn't have to box the OpWithError being returned.
-// The box is just to make it easier to get a prototype refactor working.
-type OpCreator =
- fn(cli: &Cli, base: &msg::Base<'_>, data: deno_buf) -> Box<OpWithError>;
-
-#[inline]
-fn empty_buf() -> Buf {
- Box::new([])
-}
-
-/// Processes raw messages from JavaScript.
-/// This functions invoked every time libdeno.send() is called.
-/// control corresponds to the first argument of libdeno.send().
-/// data corresponds to the second argument of libdeno.send().
-pub fn dispatch(
- cli: &Cli,
- control: &[u8],
- zero_copy: deno_buf,
-) -> (bool, Box<Op>) {
- let bytes_sent_control = control.len();
- let bytes_sent_zero_copy = zero_copy.len();
- let base = msg::get_root_as_base(&control);
- let is_sync = base.sync();
- let inner_type = base.inner_type();
- let cmd_id = base.cmd_id();
-
- let op: Box<OpWithError> = {
- // Handle regular ops.
- let op_creator: OpCreator = match inner_type {
- msg::Any::Accept => op_accept,
- msg::Any::Chdir => op_chdir,
- msg::Any::Chmod => op_chmod,
- msg::Any::Close => op_close,
- msg::Any::CopyFile => op_copy_file,
- msg::Any::Cwd => op_cwd,
- msg::Any::Dial => op_dial,
- msg::Any::Environ => op_env,
- msg::Any::Exit => op_exit,
- msg::Any::Fetch => op_fetch,
- msg::Any::FetchModuleMetaData => op_fetch_module_meta_data,
- msg::Any::FormatError => op_format_error,
- msg::Any::GlobalTimer => op_global_timer,
- msg::Any::GlobalTimerStop => op_global_timer_stop,
- msg::Any::IsTTY => op_is_tty,
- msg::Any::Listen => op_listen,
- msg::Any::MakeTempDir => op_make_temp_dir,
- msg::Any::Metrics => op_metrics,
- msg::Any::Mkdir => op_mkdir,
- msg::Any::Now => op_now,
- msg::Any::Open => op_open,
- msg::Any::PermissionRevoke => op_revoke_permission,
- msg::Any::Permissions => op_permissions,
- msg::Any::Read => op_read,
- msg::Any::ReadDir => op_read_dir,
- msg::Any::ReadFile => op_read_file,
- msg::Any::Readlink => op_read_link,
- msg::Any::Remove => op_remove,
- msg::Any::Rename => op_rename,
- msg::Any::ReplReadline => op_repl_readline,
- msg::Any::ReplStart => op_repl_start,
- msg::Any::Resources => op_resources,
- msg::Any::Run => op_run,
- msg::Any::RunStatus => op_run_status,
- msg::Any::Seek => op_seek,
- msg::Any::SetEnv => op_set_env,
- msg::Any::Shutdown => op_shutdown,
- msg::Any::Start => op_start,
- msg::Any::Stat => op_stat,
- msg::Any::Symlink => op_symlink,
- msg::Any::Truncate => op_truncate,
- msg::Any::WorkerGetMessage => op_worker_get_message,
- msg::Any::WorkerPostMessage => op_worker_post_message,
- msg::Any::Write => op_write,
- msg::Any::WriteFile => op_write_file,
- _ => panic!(format!(
- "Unhandled message {}",
- msg::enum_name_any(inner_type)
- )),
- };
- op_creator(&cli, &base, zero_copy)
- };
-
- cli
- .state
- .metrics_op_dispatched(bytes_sent_control, bytes_sent_zero_copy);
- let state = cli.state.clone();
-
- let boxed_op = Box::new(
- op.or_else(move |err: DenoError| -> Result<Buf, ()> {
- debug!("op err {}", err);
- // No matter whether we got an Err or Ok, we want a serialized message to
- // send back. So transform the DenoError into a deno_buf.
- let builder = &mut FlatBufferBuilder::new();
- let errmsg_offset = builder.create_string(&format!("{}", err));
- Ok(serialize_response(
- cmd_id,
- builder,
- msg::BaseArgs {
- error: Some(errmsg_offset),
- error_kind: err.kind(),
- ..Default::default()
- },
- ))
- }).and_then(move |buf: Buf| -> Result<Buf, ()> {
- // Handle empty responses. For sync responses we just want
- // to send null. For async we want to send a small message
- // with the cmd_id.
- let buf = if is_sync || buf.len() > 0 {
- buf
- } else {
- let builder = &mut FlatBufferBuilder::new();
- serialize_response(
- cmd_id,
- builder,
- msg::BaseArgs {
- ..Default::default()
- },
- )
- };
- state.metrics_op_completed(buf.len());
- Ok(buf)
- }).map_err(|err| panic!("unexpected error {:?}", err)),
- );
-
- debug!(
- "msg_from_js {} sync {}",
- msg::enum_name_any(inner_type),
- base.sync()
- );
- (base.sync(), boxed_op)
-}
-
-fn op_now(
- _cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- let start = SystemTime::now();
- let since_the_epoch = start.duration_since(UNIX_EPOCH).unwrap();
- let time = since_the_epoch.as_secs() * 1000
- + u64::from(since_the_epoch.subsec_millis());
-
- let builder = &mut FlatBufferBuilder::new();
- let inner = msg::NowRes::create(builder, &msg::NowResArgs { time });
- ok_future(serialize_response(
- base.cmd_id(),
- builder,
- msg::BaseArgs {
- inner: Some(inner.as_union_value()),
- inner_type: msg::Any::NowRes,
- ..Default::default()
- },
- ))
-}
-
-fn op_is_tty(
- _cli: &Cli,
- base: &msg::Base<'_>,
- _data: deno_buf,
-) -> Box<OpWithError> {
- let builder = &mut FlatBufferBuilder::new();
- let inner = msg::IsTTYRes::create(
- builder,
- &msg::IsTTYResArgs {
- stdin: atty::is(atty::Stream::Stdin),
- stdout: atty::is(atty::Stream::Stdout),
- stderr: atty::is(atty::Stream::Stderr),
- },
- );
- ok_future(serialize_response(
- base.cmd_id(),
- builder,
- msg::BaseArgs {
- inner: Some(inner.as_union_value()),
- inner_type: msg::Any::IsTTYRes,
- ..Default::default()
- },
- ))
-}
-
-fn op_exit(
- _cli: &Cli,
- base: &msg::Base<'_>,
- _data: deno_buf,
-) -> Box<OpWithError> {
- let inner = base.inner_as_exit().unwrap();
- std::process::exit(inner.code())
-}
-
-fn op_start(
- cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- let mut builder = FlatBufferBuilder::new();
-
- let argv = cli
- .state
- .argv
- .iter()
- .map(|s| s.as_str())
- .collect::<Vec<_>>();
- let argv_off = builder.create_vector_of_strings(argv.as_slice());
-
- let cwd_path = std::env::current_dir().unwrap();
- let cwd_off =
- builder.create_string(deno_fs::normalize_path(cwd_path.as_ref()).as_ref());
-
- let exec_path =
- builder.create_string(std::env::current_exe().unwrap().to_str().unwrap());
-
- let v8_version = version::v8();
- let v8_version_off = builder.create_string(v8_version);
-
- let deno_version = version::DENO;
- let deno_version_off = builder.create_string(deno_version);
-
- let main_module = cli.state.main_module().map(|m| builder.create_string(&m));
-
- let inner = msg::StartRes::create(
- &mut builder,
- &msg::StartResArgs {
- cwd: Some(cwd_off),
- pid: std::process::id(),
- argv: Some(argv_off),
- main_module,
- debug_flag: cli.state.flags.log_debug,
- types_flag: cli.state.flags.types,
- version_flag: cli.state.flags.version,
- v8_version: Some(v8_version_off),
- deno_version: Some(deno_version_off),
- no_color: !ansi::use_color(),
- exec_path: Some(exec_path),
- ..Default::default()
- },
- );
-
- ok_future(serialize_response(
- base.cmd_id(),
- &mut builder,
- msg::BaseArgs {
- inner_type: msg::Any::StartRes,
- inner: Some(inner.as_union_value()),
- ..Default::default()
- },
- ))
-}
-
-fn op_format_error(
- cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- let inner = base.inner_as_format_error().unwrap();
- let orig_error = String::from(inner.error().unwrap());
-
- let js_error = JSError::from_v8_exception(&orig_error).unwrap();
- let js_error_mapped = apply_source_map(&js_error, &cli.state.dir);
- let js_error_string = JSErrorColor(&js_error_mapped).to_string();
-
- let mut builder = FlatBufferBuilder::new();
- let new_error = builder.create_string(&js_error_string);
-
- let inner = msg::FormatErrorRes::create(
- &mut builder,
- &msg::FormatErrorResArgs {
- error: Some(new_error),
- ..Default::default()
- },
- );
-
- ok_future(serialize_response(
- base.cmd_id(),
- &mut builder,
- msg::BaseArgs {
- inner_type: msg::Any::FormatErrorRes,
- inner: Some(inner.as_union_value()),
- ..Default::default()
- },
- ))
-}
-
-fn serialize_response(
- cmd_id: u32,
- builder: &mut FlatBufferBuilder<'_>,
- mut args: msg::BaseArgs<'_>,
-) -> Buf {
- args.cmd_id = cmd_id;
- let base = msg::Base::create(builder, &args);
- msg::finish_base_buffer(builder, base);
- let data = builder.finished_data();
- // println!("serialize_response {:x?}", data);
- data.into()
-}
-
-#[inline]
-pub fn ok_future(buf: Buf) -> Box<OpWithError> {
- Box::new(futures::future::ok(buf))
-}
-
-// Shout out to Earl Sweatshirt.
-#[inline]
-pub fn odd_future(err: DenoError) -> Box<OpWithError> {
- Box::new(futures::future::err(err))
-}
-
-// https://github.com/denoland/deno/blob/golang/os.go#L100-L154
-fn op_fetch_module_meta_data(
- cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- let inner = base.inner_as_fetch_module_meta_data().unwrap();
- let cmd_id = base.cmd_id();
- let specifier = inner.specifier().unwrap();
- let referrer = inner.referrer().unwrap();
-
- // Check for allow read since this operation could be used to read from the file system.
- if !cli.permissions.allows_read() {
- debug!("No read permission for fetch_module_meta_data");
- return odd_future(permission_denied());
- }
-
- // Check for allow write since this operation could be used to write to the file system.
- if !cli.permissions.allows_write() {
- debug!("No network permission for fetch_module_meta_data");
- return odd_future(permission_denied());
- }
-
- // Check for allow net since this operation could be used to make https/http requests.
- if !cli.permissions.allows_net() {
- debug!("No network permission for fetch_module_meta_data");
- return odd_future(permission_denied());
- }
-
- assert_eq!(
- cli.state.dir.root.join("gen"),
- cli.state.dir.gen,
- "Sanity check"
- );
-
- Box::new(futures::future::result(|| -> OpResult {
- let builder = &mut FlatBufferBuilder::new();
- let out = cli.state.dir.fetch_module_meta_data(specifier, referrer)?;
- let data_off = builder.create_vector(out.source_code.as_slice());
- let msg_args = msg::FetchModuleMetaDataResArgs {
- module_name: Some(builder.create_string(&out.module_name)),
- filename: Some(builder.create_string(&out.filename)),
- media_type: out.media_type,
- data: Some(data_off),
- };
- let inner = msg::FetchModuleMetaDataRes::create(builder, &msg_args);
- Ok(serialize_response(
- cmd_id,
- builder,
- msg::BaseArgs {
- inner: Some(inner.as_union_value()),
- inner_type: msg::Any::FetchModuleMetaDataRes,
- ..Default::default()
- },
- ))
- }()))
-}
-
-fn op_chdir(
- _cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- let inner = base.inner_as_chdir().unwrap();
- let directory = inner.directory().unwrap();
- Box::new(futures::future::result(|| -> OpResult {
- std::env::set_current_dir(&directory)?;
- Ok(empty_buf())
- }()))
-}
-
-fn op_global_timer_stop(
- cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert!(base.sync());
- assert_eq!(data.len(), 0);
- let mut t = cli.state.global_timer.lock().unwrap();
- t.cancel();
- ok_future(empty_buf())
-}
-
-fn op_global_timer(
- cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert!(!base.sync());
- assert_eq!(data.len(), 0);
- let cmd_id = base.cmd_id();
- let inner = base.inner_as_global_timer().unwrap();
- let val = inner.timeout();
- assert!(val >= 0);
-
- let mut t = cli.state.global_timer.lock().unwrap();
- let deadline = Instant::now() + Duration::from_millis(val as u64);
- let f = t.new_timeout(deadline);
-
- Box::new(f.then(move |_| {
- let builder = &mut FlatBufferBuilder::new();
- let inner =
- msg::GlobalTimerRes::create(builder, &msg::GlobalTimerResArgs {});
- Ok(serialize_response(
- cmd_id,
- builder,
- msg::BaseArgs {
- inner: Some(inner.as_union_value()),
- inner_type: msg::Any::GlobalTimerRes,
- ..Default::default()
- },
- ))
- }))
-}
-
-fn op_set_env(
- cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- let inner = base.inner_as_set_env().unwrap();
- let key = inner.key().unwrap();
- let value = inner.value().unwrap();
- if let Err(e) = cli.check_env() {
- return odd_future(e);
- }
- std::env::set_var(key, value);
- ok_future(empty_buf())
-}
-
-fn op_env(cli: &Cli, base: &msg::Base<'_>, data: deno_buf) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- let cmd_id = base.cmd_id();
-
- if let Err(e) = cli.check_env() {
- return odd_future(e);
- }
-
- let builder = &mut FlatBufferBuilder::new();
- let vars: Vec<_> = std::env::vars()
- .map(|(key, value)| msg_util::serialize_key_value(builder, &key, &value))
- .collect();
- let tables = builder.create_vector(&vars);
- let inner = msg::EnvironRes::create(
- builder,
- &msg::EnvironResArgs { map: Some(tables) },
- );
- ok_future(serialize_response(
- cmd_id,
- builder,
- msg::BaseArgs {
- inner: Some(inner.as_union_value()),
- inner_type: msg::Any::EnvironRes,
- ..Default::default()
- },
- ))
-}
-
-fn op_permissions(
- cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- let cmd_id = base.cmd_id();
- let builder = &mut FlatBufferBuilder::new();
- let inner = msg::PermissionsRes::create(
- builder,
- &msg::PermissionsResArgs {
- run: cli.permissions.allows_run(),
- read: cli.permissions.allows_read(),
- write: cli.permissions.allows_write(),
- net: cli.permissions.allows_net(),
- env: cli.permissions.allows_env(),
- },
- );
- ok_future(serialize_response(
- cmd_id,
- builder,
- msg::BaseArgs {
- inner: Some(inner.as_union_value()),
- inner_type: msg::Any::PermissionsRes,
- ..Default::default()
- },
- ))
-}
-
-fn op_revoke_permission(
- cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- let inner = base.inner_as_permission_revoke().unwrap();
- let permission = inner.permission().unwrap();
- let result = match permission {
- "run" => cli.permissions.revoke_run(),
- "read" => cli.permissions.revoke_read(),
- "write" => cli.permissions.revoke_write(),
- "net" => cli.permissions.revoke_net(),
- "env" => cli.permissions.revoke_env(),
- _ => Ok(()),
- };
- if let Err(e) = result {
- return odd_future(e);
- }
- ok_future(empty_buf())
-}
-
-fn op_fetch(
- cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- let inner = base.inner_as_fetch().unwrap();
- let cmd_id = base.cmd_id();
-
- let header = inner.header().unwrap();
- assert!(header.is_request());
- let url = header.url().unwrap();
-
- let body = if data.is_empty() {
- hyper::Body::empty()
- } else {
- hyper::Body::from(Vec::from(&*data))
- };
-
- let maybe_req = msg_util::deserialize_request(header, body);
- if let Err(e) = maybe_req {
- return odd_future(e);
- }
- let req = maybe_req.unwrap();
-
- if let Err(e) = cli.check_net(url) {
- return odd_future(e);
- }
-
- let client = http_util::get_client();
-
- debug!("Before fetch {}", url);
- let future =
- client
- .request(req)
- .map_err(DenoError::from)
- .and_then(move |res| {
- let builder = &mut FlatBufferBuilder::new();
- let header_off = msg_util::serialize_http_response(builder, &res);
- let body = res.into_body();
- let body_resource = resources::add_hyper_body(body);
- let inner = msg::FetchRes::create(
- builder,
- &msg::FetchResArgs {
- header: Some(header_off),
- body_rid: body_resource.rid,
- },
- );
-
- Ok(serialize_response(
- cmd_id,
- builder,
- msg::BaseArgs {
- inner: Some(inner.as_union_value()),
- inner_type: msg::Any::FetchRes,
- ..Default::default()
- },
- ))
- });
- Box::new(future)
-}
-
-// This is just type conversion. Implement From trait?
-// See https://github.com/tokio-rs/tokio/blob/ffd73a64e7ec497622b7f939e38017afe7124dc4/tokio-fs/src/lib.rs#L76-L85
-fn convert_blocking<F>(f: F) -> Poll<Buf, DenoError>
-where
- F: FnOnce() -> DenoResult<Buf>,
-{
- use futures::Async::*;
- match tokio_threadpool::blocking(f) {
- Ok(Ready(Ok(v))) => Ok(v.into()),
- Ok(Ready(Err(err))) => Err(err),
- Ok(NotReady) => Ok(NotReady),
- Err(err) => panic!("blocking error {}", err),
- }
-}
-
-fn blocking<F>(is_sync: bool, f: F) -> Box<OpWithError>
-where
- F: 'static + Send + FnOnce() -> DenoResult<Buf>,
-{
- if is_sync {
- Box::new(futures::future::result(f()))
- } else {
- Box::new(tokio_util::poll_fn(move || convert_blocking(f)))
- }
-}
-
-fn op_make_temp_dir(
- cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- let base = Box::new(*base);
- let inner = base.inner_as_make_temp_dir().unwrap();
- let cmd_id = base.cmd_id();
-
- // FIXME
- if let Err(e) = cli.check_write("make_temp") {
- return odd_future(e);
- }
-
- let dir = inner.dir().map(PathBuf::from);
- let prefix = inner.prefix().map(String::from);
- let suffix = inner.suffix().map(String::from);
-
- blocking(base.sync(), move || -> OpResult {
- // TODO(piscisaureus): use byte vector for paths, not a string.
- // See https://github.com/denoland/deno/issues/627.
- // We can't assume that paths are always valid utf8 strings.
- let path = deno_fs::make_temp_dir(
- // Converting Option<String> to Option<&str>
- dir.as_ref().map(|x| &**x),
- prefix.as_ref().map(|x| &**x),
- suffix.as_ref().map(|x| &**x),
- )?;
- let builder = &mut FlatBufferBuilder::new();
- let path_off = builder.create_string(path.to_str().unwrap());
- let inner = msg::MakeTempDirRes::create(
- builder,
- &msg::MakeTempDirResArgs {
- path: Some(path_off),
- },
- );
- Ok(serialize_response(
- cmd_id,
- builder,
- msg::BaseArgs {
- inner: Some(inner.as_union_value()),
- inner_type: msg::Any::MakeTempDirRes,
- ..Default::default()
- },
- ))
- })
-}
-
-fn op_mkdir(
- cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- let inner = base.inner_as_mkdir().unwrap();
- let path = String::from(inner.path().unwrap());
- let recursive = inner.recursive();
- let mode = inner.mode();
-
- if let Err(e) = cli.check_write(&path) {
- return odd_future(e);
- }
-
- blocking(base.sync(), move || {
- debug!("op_mkdir {}", path);
- deno_fs::mkdir(Path::new(&path), mode, recursive)?;
- Ok(empty_buf())
- })
-}
-
-fn op_chmod(
- cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- let inner = base.inner_as_chmod().unwrap();
- let _mode = inner.mode();
- let path = String::from(inner.path().unwrap());
-
- if let Err(e) = cli.check_write(&path) {
- return odd_future(e);
- }
-
- blocking(base.sync(), move || {
- debug!("op_chmod {}", &path);
- let path = PathBuf::from(&path);
- // Still check file/dir exists on windows
- let _metadata = fs::metadata(&path)?;
- // Only work in unix
- #[cfg(any(unix))]
- {
- // We need to use underscore to compile in Windows.
- #[cfg_attr(
- feature = "cargo-clippy",
- allow(clippy::used_underscore_binding)
- )]
- let mut permissions = _metadata.permissions();
- #[cfg_attr(
- feature = "cargo-clippy",
- allow(clippy::used_underscore_binding)
- )]
- permissions.set_mode(_mode);
- fs::set_permissions(&path, permissions)?;
- }
- Ok(empty_buf())
- })
-}
-
-fn op_open(
- cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- let cmd_id = base.cmd_id();
- let inner = base.inner_as_open().unwrap();
- let filename_str = inner.filename().unwrap();
- let filename = PathBuf::from(&filename_str);
- let mode = inner.mode().unwrap();
-
- let mut open_options = tokio::fs::OpenOptions::new();
-
- match mode {
- "r" => {
- open_options.read(true);
- }
- "r+" => {
- open_options.read(true).write(true);
- }
- "w" => {
- open_options.create(true).write(true).truncate(true);
- }
- "w+" => {
- open_options
- .read(true)
- .create(true)
- .write(true)
- .truncate(true);
- }
- "a" => {
- open_options.create(true).append(true);
- }
- "a+" => {
- open_options.read(true).create(true).append(true);
- }
- "x" => {
- open_options.create_new(true).write(true);
- }
- "x+" => {
- open_options.create_new(true).read(true).write(true);
- }
- &_ => {
- panic!("Unknown file open mode.");
- }
- }
-
- match mode {
- "r" => {
- if let Err(e) = cli.check_read(&filename_str) {
- return odd_future(e);
- }
- }
- "w" | "a" | "x" => {
- if let Err(e) = cli.check_write(&filename_str) {
- return odd_future(e);
- }
- }
- &_ => {
- if let Err(e) = cli.check_read(&filename_str) {
- return odd_future(e);
- }
- if let Err(e) = cli.check_write(&filename_str) {
- return odd_future(e);
- }
- }
- }
-
- let op = open_options
- .open(filename)
- .map_err(DenoError::from)
- .and_then(move |fs_file| -> OpResult {
- let resource = resources::add_fs_file(fs_file);
- let builder = &mut FlatBufferBuilder::new();
- let inner =
- msg::OpenRes::create(builder, &msg::OpenResArgs { rid: resource.rid });
- Ok(serialize_response(
- cmd_id,
- builder,
- msg::BaseArgs {
- inner: Some(inner.as_union_value()),
- inner_type: msg::Any::OpenRes,
- ..Default::default()
- },
- ))
- });
- Box::new(op)
-}
-
-fn op_close(
- _cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- let inner = base.inner_as_close().unwrap();
- let rid = inner.rid();
- match resources::lookup(rid) {
- None => odd_future(errors::bad_resource()),
- Some(resource) => {
- resource.close();
- ok_future(empty_buf())
- }
- }
-}
-
-fn op_shutdown(
- _cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- let inner = base.inner_as_shutdown().unwrap();
- let rid = inner.rid();
- let how = inner.how();
- match resources::lookup(rid) {
- None => odd_future(errors::bad_resource()),
- Some(mut resource) => {
- let shutdown_mode = match how {
- 0 => Shutdown::Read,
- 1 => Shutdown::Write,
- _ => unimplemented!(),
- };
- blocking(base.sync(), move || {
- // Use UFCS for disambiguation
- Resource::shutdown(&mut resource, shutdown_mode)?;
- Ok(empty_buf())
- })
- }
- }
-}
-
-fn op_read(
- _cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- let cmd_id = base.cmd_id();
- let inner = base.inner_as_read().unwrap();
- let rid = inner.rid();
-
- match resources::lookup(rid) {
- None => odd_future(errors::bad_resource()),
- Some(resource) => {
- let op = tokio::io::read(resource, data)
- .map_err(DenoError::from)
- .and_then(move |(_resource, _buf, nread)| {
- let builder = &mut FlatBufferBuilder::new();
- let inner = msg::ReadRes::create(
- builder,
- &msg::ReadResArgs {
- nread: nread as u32,
- eof: nread == 0,
- },
- );
- Ok(serialize_response(
- cmd_id,
- builder,
- msg::BaseArgs {
- inner: Some(inner.as_union_value()),
- inner_type: msg::Any::ReadRes,
- ..Default::default()
- },
- ))
- });
- Box::new(op)
- }
- }
-}
-
-fn op_write(
- _cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- let cmd_id = base.cmd_id();
- let inner = base.inner_as_write().unwrap();
- let rid = inner.rid();
-
- match resources::lookup(rid) {
- None => odd_future(errors::bad_resource()),
- Some(resource) => {
- let op = tokio_write::write(resource, data)
- .map_err(DenoError::from)
- .and_then(move |(_resource, _buf, nwritten)| {
- let builder = &mut FlatBufferBuilder::new();
- let inner = msg::WriteRes::create(
- builder,
- &msg::WriteResArgs {
- nbyte: nwritten as u32,
- },
- );
- Ok(serialize_response(
- cmd_id,
- builder,
- msg::BaseArgs {
- inner: Some(inner.as_union_value()),
- inner_type: msg::Any::WriteRes,
- ..Default::default()
- },
- ))
- });
- Box::new(op)
- }
- }
-}
-
-fn op_seek(
- _cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- let _cmd_id = base.cmd_id();
- let inner = base.inner_as_seek().unwrap();
- let rid = inner.rid();
- let offset = inner.offset();
- let whence = inner.whence();
-
- match resources::lookup(rid) {
- None => odd_future(errors::bad_resource()),
- Some(resource) => {
- let op = resources::seek(resource, offset, whence)
- .and_then(move |_| Ok(empty_buf()));
- Box::new(op)
- }
- }
-}
-
-fn op_remove(
- cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- let inner = base.inner_as_remove().unwrap();
- let path_ = inner.path().unwrap();
- let path = PathBuf::from(path_);
- let recursive = inner.recursive();
-
- if let Err(e) = cli.check_write(path.to_str().unwrap()) {
- return odd_future(e);
- }
-
- blocking(base.sync(), move || {
- debug!("op_remove {}", path.display());
- let metadata = fs::metadata(&path)?;
- if metadata.is_file() {
- fs::remove_file(&path)?;
- } else if recursive {
- remove_dir_all(&path)?;
- } else {
- fs::remove_dir(&path)?;
- }
- Ok(empty_buf())
- })
-}
-
-// Prototype https://github.com/denoland/deno/blob/golang/os.go#L171-L184
-fn op_read_file(
- cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- let inner = base.inner_as_read_file().unwrap();
- let cmd_id = base.cmd_id();
- let filename_ = inner.filename().unwrap();
- let filename = PathBuf::from(filename_);
- debug!("op_read_file {}", filename.display());
- if let Err(e) = cli.check_read(&filename_) {
- return odd_future(e);
- }
- blocking(base.sync(), move || {
- let vec = fs::read(&filename)?;
- // Build the response message. memcpy data into inner.
- // TODO(ry) zero-copy.
- let builder = &mut FlatBufferBuilder::new();
- let data_off = builder.create_vector(vec.as_slice());
- let inner = msg::ReadFileRes::create(
- builder,
- &msg::ReadFileResArgs {
- data: Some(data_off),
- },
- );
- Ok(serialize_response(
- cmd_id,
- builder,
- msg::BaseArgs {
- inner: Some(inner.as_union_value()),
- inner_type: msg::Any::ReadFileRes,
- ..Default::default()
- },
- ))
- })
-}
-
-fn op_copy_file(
- cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- let inner = base.inner_as_copy_file().unwrap();
- let from_ = inner.from().unwrap();
- let from = PathBuf::from(from_);
- let to_ = inner.to().unwrap();
- let to = PathBuf::from(to_);
-
- if let Err(e) = cli.check_read(&from_) {
- return odd_future(e);
- }
- if let Err(e) = cli.check_write(&to_) {
- return odd_future(e);
- }
-
- debug!("op_copy_file {} {}", from.display(), to.display());
- blocking(base.sync(), move || {
- // On *nix, Rust deem non-existent path as invalid input
- // See https://github.com/rust-lang/rust/issues/54800
- // Once the issue is reolved, we should remove this workaround.
- if cfg!(unix) && !from.is_file() {
- return Err(errors::new(
- ErrorKind::NotFound,
- "File not found".to_string(),
- ));
- }
-
- fs::copy(&from, &to)?;
- Ok(empty_buf())
- })
-}
-
-macro_rules! to_seconds {
- ($time:expr) => {{
- // Unwrap is safe here as if the file is before the unix epoch
- // something is very wrong.
- $time
- .and_then(|t| Ok(t.duration_since(UNIX_EPOCH).unwrap().as_secs()))
- .unwrap_or(0)
- }};
-}
-
-#[cfg(any(unix))]
-fn get_mode(perm: &fs::Permissions) -> u32 {
- perm.mode()
-}
-
-#[cfg(not(any(unix)))]
-fn get_mode(_perm: &fs::Permissions) -> u32 {
- 0
-}
-
-fn op_cwd(
- _cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- let cmd_id = base.cmd_id();
- Box::new(futures::future::result(|| -> OpResult {
- let path = std::env::current_dir()?;
- let builder = &mut FlatBufferBuilder::new();
- let cwd =
- builder.create_string(&path.into_os_string().into_string().unwrap());
- let inner =
- msg::CwdRes::create(builder, &msg::CwdResArgs { cwd: Some(cwd) });
- Ok(serialize_response(
- cmd_id,
- builder,
- msg::BaseArgs {
- inner: Some(inner.as_union_value()),
- inner_type: msg::Any::CwdRes,
- ..Default::default()
- },
- ))
- }()))
-}
-
-fn op_stat(
- cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- let inner = base.inner_as_stat().unwrap();
- let cmd_id = base.cmd_id();
- let filename_ = inner.filename().unwrap();
- let filename = PathBuf::from(filename_);
- let lstat = inner.lstat();
-
- if let Err(e) = cli.check_read(&filename_) {
- return odd_future(e);
- }
-
- blocking(base.sync(), move || {
- let builder = &mut FlatBufferBuilder::new();
- debug!("op_stat {} {}", filename.display(), lstat);
- let metadata = if lstat {
- fs::symlink_metadata(&filename)?
- } else {
- fs::metadata(&filename)?
- };
-
- let inner = msg::StatRes::create(
- builder,
- &msg::StatResArgs {
- is_file: metadata.is_file(),
- is_symlink: metadata.file_type().is_symlink(),
- len: metadata.len(),
- modified: to_seconds!(metadata.modified()),
- accessed: to_seconds!(metadata.accessed()),
- created: to_seconds!(metadata.created()),
- mode: get_mode(&metadata.permissions()),
- has_mode: cfg!(target_family = "unix"),
- ..Default::default()
- },
- );
-
- Ok(serialize_response(
- cmd_id,
- builder,
- msg::BaseArgs {
- inner: Some(inner.as_union_value()),
- inner_type: msg::Any::StatRes,
- ..Default::default()
- },
- ))
- })
-}
-
-fn op_read_dir(
- cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- let inner = base.inner_as_read_dir().unwrap();
- let cmd_id = base.cmd_id();
- let path = String::from(inner.path().unwrap());
-
- if let Err(e) = cli.check_read(&path) {
- return odd_future(e);
- }
-
- blocking(base.sync(), move || -> OpResult {
- debug!("op_read_dir {}", path);
- let builder = &mut FlatBufferBuilder::new();
- let entries: Vec<_> = fs::read_dir(Path::new(&path))?
- .map(|entry| {
- let entry = entry.unwrap();
- let metadata = entry.metadata().unwrap();
- let file_type = metadata.file_type();
- let name = builder.create_string(entry.file_name().to_str().unwrap());
- let path = builder.create_string(entry.path().to_str().unwrap());
-
- msg::StatRes::create(
- builder,
- &msg::StatResArgs {
- is_file: file_type.is_file(),
- is_symlink: file_type.is_symlink(),
- len: metadata.len(),
- modified: to_seconds!(metadata.modified()),
- accessed: to_seconds!(metadata.accessed()),
- created: to_seconds!(metadata.created()),
- name: Some(name),
- path: Some(path),
- mode: get_mode(&metadata.permissions()),
- has_mode: cfg!(target_family = "unix"),
- },
- )
- }).collect();
-
- let entries = builder.create_vector(&entries);
- let inner = msg::ReadDirRes::create(
- builder,
- &msg::ReadDirResArgs {
- entries: Some(entries),
- },
- );
- Ok(serialize_response(
- cmd_id,
- builder,
- msg::BaseArgs {
- inner: Some(inner.as_union_value()),
- inner_type: msg::Any::ReadDirRes,
- ..Default::default()
- },
- ))
- })
-}
-
-fn op_write_file(
- cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- let inner = base.inner_as_write_file().unwrap();
- let filename = String::from(inner.filename().unwrap());
- let update_perm = inner.update_perm();
- let perm = inner.perm();
- let is_create = inner.is_create();
- let is_append = inner.is_append();
-
- if let Err(e) = cli.check_write(&filename) {
- return odd_future(e);
- }
-
- blocking(base.sync(), move || -> OpResult {
- debug!("op_write_file {} {}", filename, data.len());
- deno_fs::write_file_2(
- Path::new(&filename),
- data,
- update_perm,
- perm,
- is_create,
- is_append,
- )?;
- Ok(empty_buf())
- })
-}
-
-fn op_rename(
- cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- let inner = base.inner_as_rename().unwrap();
- let oldpath = PathBuf::from(inner.oldpath().unwrap());
- let newpath_ = inner.newpath().unwrap();
- let newpath = PathBuf::from(newpath_);
- if let Err(e) = cli.check_write(&newpath_) {
- return odd_future(e);
- }
- blocking(base.sync(), move || -> OpResult {
- debug!("op_rename {} {}", oldpath.display(), newpath.display());
- fs::rename(&oldpath, &newpath)?;
- Ok(empty_buf())
- })
-}
-
-fn op_symlink(
- cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- let inner = base.inner_as_symlink().unwrap();
- let oldname = PathBuf::from(inner.oldname().unwrap());
- let newname_ = inner.newname().unwrap();
- let newname = PathBuf::from(newname_);
-
- if let Err(e) = cli.check_write(&newname_) {
- return odd_future(e);
- }
- // TODO Use type for Windows.
- if cfg!(windows) {
- return odd_future(errors::new(
- ErrorKind::Other,
- "Not implemented".to_string(),
- ));
- }
- blocking(base.sync(), move || -> OpResult {
- debug!("op_symlink {} {}", oldname.display(), newname.display());
- #[cfg(any(unix))]
- std::os::unix::fs::symlink(&oldname, &newname)?;
- Ok(empty_buf())
- })
-}
-
-fn op_read_link(
- cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- let inner = base.inner_as_readlink().unwrap();
- let cmd_id = base.cmd_id();
- let name_ = inner.name().unwrap();
- let name = PathBuf::from(name_);
-
- if let Err(e) = cli.check_read(&name_) {
- return odd_future(e);
- }
-
- blocking(base.sync(), move || -> OpResult {
- debug!("op_read_link {}", name.display());
- let path = fs::read_link(&name)?;
- let builder = &mut FlatBufferBuilder::new();
- let path_off = builder.create_string(path.to_str().unwrap());
- let inner = msg::ReadlinkRes::create(
- builder,
- &msg::ReadlinkResArgs {
- path: Some(path_off),
- },
- );
- Ok(serialize_response(
- cmd_id,
- builder,
- msg::BaseArgs {
- inner: Some(inner.as_union_value()),
- inner_type: msg::Any::ReadlinkRes,
- ..Default::default()
- },
- ))
- })
-}
-
-fn op_repl_start(
- cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- let inner = base.inner_as_repl_start().unwrap();
- let cmd_id = base.cmd_id();
- let history_file = String::from(inner.history_file().unwrap());
-
- debug!("op_repl_start {}", history_file);
- let history_path = repl::history_path(&cli.state.dir, &history_file);
- let repl = repl::Repl::new(history_path);
- let resource = resources::add_repl(repl);
-
- let builder = &mut FlatBufferBuilder::new();
- let inner = msg::ReplStartRes::create(
- builder,
- &msg::ReplStartResArgs { rid: resource.rid },
- );
- ok_future(serialize_response(
- cmd_id,
- builder,
- msg::BaseArgs {
- inner: Some(inner.as_union_value()),
- inner_type: msg::Any::ReplStartRes,
- ..Default::default()
- },
- ))
-}
-
-fn op_repl_readline(
- _cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- let inner = base.inner_as_repl_readline().unwrap();
- let cmd_id = base.cmd_id();
- let rid = inner.rid();
- let prompt = inner.prompt().unwrap().to_owned();
- debug!("op_repl_readline {} {}", rid, prompt);
-
- blocking(base.sync(), move || -> OpResult {
- let repl = resources::get_repl(rid)?;
- let line = repl.lock().unwrap().readline(&prompt)?;
-
- let builder = &mut FlatBufferBuilder::new();
- let line_off = builder.create_string(&line);
- let inner = msg::ReplReadlineRes::create(
- builder,
- &msg::ReplReadlineResArgs {
- line: Some(line_off),
- },
- );
- Ok(serialize_response(
- cmd_id,
- builder,
- msg::BaseArgs {
- inner: Some(inner.as_union_value()),
- inner_type: msg::Any::ReplReadlineRes,
- ..Default::default()
- },
- ))
- })
-}
-
-fn op_truncate(
- cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
-
- let inner = base.inner_as_truncate().unwrap();
- let filename = String::from(inner.name().unwrap());
- let len = inner.len();
-
- if let Err(e) = cli.check_write(&filename) {
- return odd_future(e);
- }
-
- blocking(base.sync(), move || {
- debug!("op_truncate {} {}", filename, len);
- let f = fs::OpenOptions::new().write(true).open(&filename)?;
- f.set_len(u64::from(len))?;
- Ok(empty_buf())
- })
-}
-
-fn op_listen(
- cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- if let Err(e) = cli.check_net("listen") {
- return odd_future(e);
- }
-
- let cmd_id = base.cmd_id();
- let inner = base.inner_as_listen().unwrap();
- let network = inner.network().unwrap();
- assert_eq!(network, "tcp");
- let address = inner.address().unwrap();
-
- Box::new(futures::future::result((move || {
- let addr = resolve_addr(address).wait()?;
-
- let listener = TcpListener::bind(&addr)?;
- let resource = resources::add_tcp_listener(listener);
-
- let builder = &mut FlatBufferBuilder::new();
- let inner = msg::ListenRes::create(
- builder,
- &msg::ListenResArgs { rid: resource.rid },
- );
- Ok(serialize_response(
- cmd_id,
- builder,
- msg::BaseArgs {
- inner: Some(inner.as_union_value()),
- inner_type: msg::Any::ListenRes,
- ..Default::default()
- },
- ))
- })()))
-}
-
-fn new_conn(cmd_id: u32, tcp_stream: TcpStream) -> OpResult {
- let tcp_stream_resource = resources::add_tcp_stream(tcp_stream);
- // TODO forward socket_addr to client.
-
- let builder = &mut FlatBufferBuilder::new();
- let inner = msg::NewConn::create(
- builder,
- &msg::NewConnArgs {
- rid: tcp_stream_resource.rid,
- ..Default::default()
- },
- );
- Ok(serialize_response(
- cmd_id,
- builder,
- msg::BaseArgs {
- inner: Some(inner.as_union_value()),
- inner_type: msg::Any::NewConn,
- ..Default::default()
- },
- ))
-}
-
-fn op_accept(
- cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- if let Err(e) = cli.check_net("accept") {
- return odd_future(e);
- }
- let cmd_id = base.cmd_id();
- let inner = base.inner_as_accept().unwrap();
- let server_rid = inner.rid();
-
- match resources::lookup(server_rid) {
- None => odd_future(errors::bad_resource()),
- Some(server_resource) => {
- let op = tokio_util::accept(server_resource)
- .map_err(DenoError::from)
- .and_then(move |(tcp_stream, _socket_addr)| {
- new_conn(cmd_id, tcp_stream)
- });
- Box::new(op)
- }
- }
-}
-
-fn op_dial(
- cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- if let Err(e) = cli.check_net("dial") {
- return odd_future(e);
- }
- let cmd_id = base.cmd_id();
- let inner = base.inner_as_dial().unwrap();
- let network = inner.network().unwrap();
- assert_eq!(network, "tcp"); // TODO Support others.
- let address = inner.address().unwrap();
-
- let op =
- resolve_addr(address)
- .map_err(DenoError::from)
- .and_then(move |addr| {
- TcpStream::connect(&addr)
- .map_err(DenoError::from)
- .and_then(move |tcp_stream| new_conn(cmd_id, tcp_stream))
- });
- Box::new(op)
-}
-
-fn op_metrics(
- cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- let cmd_id = base.cmd_id();
-
- let builder = &mut FlatBufferBuilder::new();
- let inner = msg::MetricsRes::create(
- builder,
- &msg::MetricsResArgs::from(&cli.state.metrics),
- );
- ok_future(serialize_response(
- cmd_id,
- builder,
- msg::BaseArgs {
- inner: Some(inner.as_union_value()),
- inner_type: msg::Any::MetricsRes,
- ..Default::default()
- },
- ))
-}
-
-fn op_resources(
- _cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- let cmd_id = base.cmd_id();
-
- let builder = &mut FlatBufferBuilder::new();
- let serialized_resources = table_entries();
-
- let res: Vec<_> = serialized_resources
- .iter()
- .map(|(key, value)| {
- let repr = builder.create_string(value);
-
- msg::Resource::create(
- builder,
- &msg::ResourceArgs {
- rid: *key,
- repr: Some(repr),
- },
- )
- }).collect();
-
- let resources = builder.create_vector(&res);
- let inner = msg::ResourcesRes::create(
- builder,
- &msg::ResourcesResArgs {
- resources: Some(resources),
- },
- );
-
- ok_future(serialize_response(
- cmd_id,
- builder,
- msg::BaseArgs {
- inner: Some(inner.as_union_value()),
- inner_type: msg::Any::ResourcesRes,
- ..Default::default()
- },
- ))
-}
-
-fn subprocess_stdio_map(v: msg::ProcessStdio) -> std::process::Stdio {
- match v {
- msg::ProcessStdio::Inherit => std::process::Stdio::inherit(),
- msg::ProcessStdio::Piped => std::process::Stdio::piped(),
- msg::ProcessStdio::Null => std::process::Stdio::null(),
- }
-}
-
-fn op_run(cli: &Cli, base: &msg::Base<'_>, data: deno_buf) -> Box<OpWithError> {
- assert!(base.sync());
- let cmd_id = base.cmd_id();
-
- if let Err(e) = cli.check_run() {
- return odd_future(e);
- }
-
- assert_eq!(data.len(), 0);
- let inner = base.inner_as_run().unwrap();
- let args = inner.args().unwrap();
- let env = inner.env().unwrap();
- let cwd = inner.cwd();
-
- let mut c = Command::new(args.get(0));
- (1..args.len()).for_each(|i| {
- let arg = args.get(i);
- c.arg(arg);
- });
- cwd.map(|d| c.current_dir(d));
- (0..env.len()).for_each(|i| {
- let entry = env.get(i);
- c.env(entry.key().unwrap(), entry.value().unwrap());
- });
-
- c.stdin(subprocess_stdio_map(inner.stdin()));
- c.stdout(subprocess_stdio_map(inner.stdout()));
- c.stderr(subprocess_stdio_map(inner.stderr()));
-
- // Spawn the command.
- let child = match c.spawn_async() {
- Ok(v) => v,
- Err(err) => {
- return odd_future(err.into());
- }
- };
-
- let pid = child.id();
- let resources = resources::add_child(child);
-
- let mut res_args = msg::RunResArgs {
- rid: resources.child_rid,
- pid,
- ..Default::default()
- };
-
- if let Some(stdin_rid) = resources.stdin_rid {
- res_args.stdin_rid = stdin_rid;
- }
- if let Some(stdout_rid) = resources.stdout_rid {
- res_args.stdout_rid = stdout_rid;
- }
- if let Some(stderr_rid) = resources.stderr_rid {
- res_args.stderr_rid = stderr_rid;
- }
-
- let builder = &mut FlatBufferBuilder::new();
- let inner = msg::RunRes::create(builder, &res_args);
- ok_future(serialize_response(
- cmd_id,
- builder,
- msg::BaseArgs {
- inner: Some(inner.as_union_value()),
- inner_type: msg::Any::RunRes,
- ..Default::default()
- },
- ))
-}
-
-fn op_run_status(
- cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- let cmd_id = base.cmd_id();
- let inner = base.inner_as_run_status().unwrap();
- let rid = inner.rid();
-
- if let Err(e) = cli.check_run() {
- return odd_future(e);
- }
-
- let future = match resources::child_status(rid) {
- Err(e) => {
- return odd_future(e);
- }
- Ok(f) => f,
- };
-
- let future = future.and_then(move |run_status| {
- let code = run_status.code();
-
- #[cfg(unix)]
- let signal = run_status.signal();
- #[cfg(not(unix))]
- let signal = None;
-
- code
- .or(signal)
- .expect("Should have either an exit code or a signal.");
- let got_signal = signal.is_some();
-
- let builder = &mut FlatBufferBuilder::new();
- let inner = msg::RunStatusRes::create(
- builder,
- &msg::RunStatusResArgs {
- got_signal,
- exit_code: code.unwrap_or(-1),
- exit_signal: signal.unwrap_or(-1),
- },
- );
- Ok(serialize_response(
- cmd_id,
- builder,
- msg::BaseArgs {
- inner: Some(inner.as_union_value()),
- inner_type: msg::Any::RunStatusRes,
- ..Default::default()
- },
- ))
- });
- Box::new(future)
-}
-
-struct GetMessageFuture {
- pub state: Arc<IsolateState>,
-}
-
-impl Future for GetMessageFuture {
- type Item = Option<Buf>;
- type Error = ();
-
- fn poll(&mut self) -> Result<Async<Self::Item>, Self::Error> {
- assert!(self.state.worker_channels.is_some());
- match self.state.worker_channels {
- None => panic!("expected worker_channels"),
- Some(ref wc) => {
- let mut wc = wc.lock().unwrap();
- wc.1.poll()
- }
- }
- }
-}
-
-fn op_worker_get_message(
- cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- assert_eq!(data.len(), 0);
- let cmd_id = base.cmd_id();
-
- let op = GetMessageFuture {
- state: cli.state.clone(),
- };
- let op = op.map_err(move |_| -> DenoError { unimplemented!() });
- let op = op.and_then(move |maybe_buf| -> DenoResult<Buf> {
- debug!("op_worker_get_message");
- let builder = &mut FlatBufferBuilder::new();
-
- let data = maybe_buf.as_ref().map(|buf| builder.create_vector(buf));
- let inner = msg::WorkerGetMessageRes::create(
- builder,
- &msg::WorkerGetMessageResArgs { data },
- );
- Ok(serialize_response(
- cmd_id,
- builder,
- msg::BaseArgs {
- inner: Some(inner.as_union_value()),
- inner_type: msg::Any::WorkerGetMessageRes,
- ..Default::default()
- },
- ))
- });
- Box::new(op)
-}
-
-fn op_worker_post_message(
- cli: &Cli,
- base: &msg::Base<'_>,
- data: deno_buf,
-) -> Box<OpWithError> {
- let cmd_id = base.cmd_id();
-
- let d = Vec::from(data.as_ref()).into_boxed_slice();
-
- assert!(cli.state.worker_channels.is_some());
- let tx = match cli.state.worker_channels {
- None => panic!("expected worker_channels"),
- Some(ref wc) => {
- let wc = wc.lock().unwrap();
- wc.0.clone()
- }
- };
- let op = tx.send(d);
- let op = op.map_err(|e| errors::new(ErrorKind::Other, e.to_string()));
- let op = op.and_then(move |_| -> DenoResult<Buf> {
- let builder = &mut FlatBufferBuilder::new();
-
- Ok(serialize_response(
- cmd_id,
- builder,
- msg::BaseArgs {
- ..Default::default()
- },
- ))
- });
- Box::new(op)
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use crate::cli::Cli;
- use crate::isolate_state::IsolateState;
- use crate::permissions::{DenoPermissions, PermissionAccessor};
-
- #[test]
- fn fetch_module_meta_fails_without_read() {
- let state = Arc::new(IsolateState::mock());
- let permissions = DenoPermissions {
- allow_write: PermissionAccessor::from(true),
- allow_env: PermissionAccessor::from(true),
- allow_net: PermissionAccessor::from(true),
- allow_run: PermissionAccessor::from(true),
- ..Default::default()
- };
- let cli = Cli::new(None, state, permissions);
- let builder = &mut FlatBufferBuilder::new();
- let fetch_msg_args = msg::FetchModuleMetaDataArgs {
- specifier: Some(builder.create_string("./somefile")),
- referrer: Some(builder.create_string(".")),
- };
- let inner = msg::FetchModuleMetaData::create(builder, &fetch_msg_args);
- let base_args = msg::BaseArgs {
- inner: Some(inner.as_union_value()),
- inner_type: msg::Any::FetchModuleMetaData,
- ..Default::default()
- };
- let base = msg::Base::create(builder, &base_args);
- msg::finish_base_buffer(builder, base);
- let data = builder.finished_data();
- let final_msg = msg::get_root_as_base(&data);
- let fetch_result =
- op_fetch_module_meta_data(&cli, &final_msg, deno_buf::empty()).wait();
- match fetch_result {
- Ok(_) => assert!(true),
- Err(e) => assert_eq!(e.to_string(), permission_denied().to_string()),
- }
- }
-
- #[test]
- fn fetch_module_meta_fails_without_write() {
- let state = Arc::new(IsolateState::mock());
- let permissions = DenoPermissions {
- allow_read: PermissionAccessor::from(true),
- allow_env: PermissionAccessor::from(true),
- allow_net: PermissionAccessor::from(true),
- allow_run: PermissionAccessor::from(true),
- ..Default::default()
- };
- let cli = Cli::new(None, state, permissions);
- let builder = &mut FlatBufferBuilder::new();
- let fetch_msg_args = msg::FetchModuleMetaDataArgs {
- specifier: Some(builder.create_string("./somefile")),
- referrer: Some(builder.create_string(".")),
- };
- let inner = msg::FetchModuleMetaData::create(builder, &fetch_msg_args);
- let base_args = msg::BaseArgs {
- inner: Some(inner.as_union_value()),
- inner_type: msg::Any::FetchModuleMetaData,
- ..Default::default()
- };
- let base = msg::Base::create(builder, &base_args);
- msg::finish_base_buffer(builder, base);
- let data = builder.finished_data();
- let final_msg = msg::get_root_as_base(&data);
- let fetch_result =
- op_fetch_module_meta_data(&cli, &final_msg, deno_buf::empty()).wait();
- match fetch_result {
- Ok(_) => assert!(true),
- Err(e) => assert_eq!(e.to_string(), permission_denied().to_string()),
- }
- }
-
- #[test]
- fn fetch_module_meta_fails_without_net() {
- let state = Arc::new(IsolateState::mock());
- let permissions = DenoPermissions {
- allow_read: PermissionAccessor::from(true),
- allow_write: PermissionAccessor::from(true),
- allow_env: PermissionAccessor::from(true),
- allow_run: PermissionAccessor::from(true),
- ..Default::default()
- };
- let cli = Cli::new(None, state, permissions);
- let builder = &mut FlatBufferBuilder::new();
- let fetch_msg_args = msg::FetchModuleMetaDataArgs {
- specifier: Some(builder.create_string("./somefile")),
- referrer: Some(builder.create_string(".")),
- };
- let inner = msg::FetchModuleMetaData::create(builder, &fetch_msg_args);
- let base_args = msg::BaseArgs {
- inner: Some(inner.as_union_value()),
- inner_type: msg::Any::FetchModuleMetaData,
- ..Default::default()
- };
- let base = msg::Base::create(builder, &base_args);
- msg::finish_base_buffer(builder, base);
- let data = builder.finished_data();
- let final_msg = msg::get_root_as_base(&data);
- let fetch_result =
- op_fetch_module_meta_data(&cli, &final_msg, deno_buf::empty()).wait();
- match fetch_result {
- Ok(_) => assert!(true),
- Err(e) => assert_eq!(e.to_string(), permission_denied().to_string()),
- }
- }
-
- #[test]
- fn fetch_module_meta_not_permission_denied_with_permissions() {
- let state = Arc::new(IsolateState::mock());
- let permissions = DenoPermissions {
- allow_read: PermissionAccessor::from(true),
- allow_write: PermissionAccessor::from(true),
- allow_net: PermissionAccessor::from(true),
- ..Default::default()
- };
- let cli = Cli::new(None, state, permissions);
- let builder = &mut FlatBufferBuilder::new();
- let fetch_msg_args = msg::FetchModuleMetaDataArgs {
- specifier: Some(builder.create_string("./somefile")),
- referrer: Some(builder.create_string(".")),
- };
- let inner = msg::FetchModuleMetaData::create(builder, &fetch_msg_args);
- let base_args = msg::BaseArgs {
- inner: Some(inner.as_union_value()),
- inner_type: msg::Any::FetchModuleMetaData,
- ..Default::default()
- };
- let base = msg::Base::create(builder, &base_args);
- msg::finish_base_buffer(builder, base);
- let data = builder.finished_data();
- let final_msg = msg::get_root_as_base(&data);
- let fetch_result =
- op_fetch_module_meta_data(&cli, &final_msg, deno_buf::empty()).wait();
- match fetch_result {
- Ok(_) => assert!(true),
- Err(e) => assert!(e.to_string() != permission_denied().to_string()),
- }
- }
-}
diff --git a/src/permissions.rs b/src/permissions.rs
deleted file mode 100644
index 9093c14f0..000000000
--- a/src/permissions.rs
+++ /dev/null
@@ -1,343 +0,0 @@
-// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-use atty;
-
-use crate::flags::DenoFlags;
-
-use ansi_term::Style;
-use crate::errors::permission_denied;
-use crate::errors::DenoResult;
-use std::fmt;
-use std::io;
-use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
-use std::sync::Arc;
-
-/// Tri-state value for storing permission state
-pub enum PermissionAccessorState {
- Allow = 0,
- Ask = 1,
- Deny = 2,
-}
-
-impl From<usize> for PermissionAccessorState {
- fn from(val: usize) -> Self {
- match val {
- 0 => PermissionAccessorState::Allow,
- 1 => PermissionAccessorState::Ask,
- 2 => PermissionAccessorState::Deny,
- _ => unreachable!(),
- }
- }
-}
-
-impl From<bool> for PermissionAccessorState {
- fn from(val: bool) -> Self {
- match val {
- true => PermissionAccessorState::Allow,
- false => PermissionAccessorState::Ask,
- }
- }
-}
-
-impl fmt::Display for PermissionAccessorState {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- PermissionAccessorState::Allow => f.pad("Allow"),
- PermissionAccessorState::Ask => f.pad("Ask"),
- PermissionAccessorState::Deny => f.pad("Deny"),
- }
- }
-}
-
-#[derive(Debug)]
-pub struct PermissionAccessor {
- state: Arc<AtomicUsize>,
-}
-
-impl PermissionAccessor {
- pub fn new(state: PermissionAccessorState) -> Self {
- Self {
- state: Arc::new(AtomicUsize::new(state as usize)),
- }
- }
-
- pub fn is_allow(&self) -> bool {
- match self.get_state() {
- PermissionAccessorState::Allow => true,
- _ => false,
- }
- }
-
- /// If the state is "Allow" walk it back to the default "Ask"
- /// Don't do anything if state is "Deny"
- pub fn revoke(&self) {
- if self.is_allow() {
- self.ask();
- }
- }
-
- pub fn allow(&self) {
- self.set_state(PermissionAccessorState::Allow)
- }
-
- pub fn ask(&self) {
- self.set_state(PermissionAccessorState::Ask)
- }
-
- pub fn deny(&self) {
- self.set_state(PermissionAccessorState::Deny)
- }
-
- /// Update this accessors state based on a PromptResult value
- /// This will only update the state if the PromptResult value
- /// is one of the "Always" values
- pub fn update_with_prompt_result(&self, prompt_result: &PromptResult) {
- match prompt_result {
- PromptResult::AllowAlways => self.allow(),
- PromptResult::DenyAlways => self.deny(),
- _ => {}
- }
- }
-
- #[inline]
- pub fn get_state(&self) -> PermissionAccessorState {
- self.state.load(Ordering::SeqCst).into()
- }
- fn set_state(&self, state: PermissionAccessorState) {
- self.state.store(state as usize, Ordering::SeqCst)
- }
-}
-
-impl From<bool> for PermissionAccessor {
- fn from(val: bool) -> Self {
- Self::new(PermissionAccessorState::from(val))
- }
-}
-
-impl Default for PermissionAccessor {
- fn default() -> Self {
- Self {
- state: Arc::new(AtomicUsize::new(PermissionAccessorState::Ask as usize)),
- }
- }
-}
-
-#[cfg_attr(feature = "cargo-clippy", allow(stutter))]
-#[derive(Debug, Default)]
-pub struct DenoPermissions {
- // Keep in sync with src/permissions.ts
- pub allow_read: PermissionAccessor,
- pub allow_write: PermissionAccessor,
- pub allow_net: PermissionAccessor,
- pub allow_env: PermissionAccessor,
- pub allow_run: PermissionAccessor,
- pub no_prompts: AtomicBool,
-}
-
-impl DenoPermissions {
- pub fn from_flags(flags: &DenoFlags) -> Self {
- Self {
- allow_read: PermissionAccessor::from(flags.allow_read),
- allow_write: PermissionAccessor::from(flags.allow_write),
- allow_env: PermissionAccessor::from(flags.allow_env),
- allow_net: PermissionAccessor::from(flags.allow_net),
- allow_run: PermissionAccessor::from(flags.allow_run),
- no_prompts: AtomicBool::new(flags.no_prompts),
- }
- }
-
- pub fn check_run(&self) -> DenoResult<()> {
- match self.allow_run.get_state() {
- PermissionAccessorState::Allow => Ok(()),
- PermissionAccessorState::Ask => {
- match self.try_permissions_prompt("access to run a subprocess") {
- Err(e) => Err(e),
- Ok(v) => {
- self.allow_run.update_with_prompt_result(&v);
- v.check()?;
- Ok(())
- }
- }
- }
- PermissionAccessorState::Deny => Err(permission_denied()),
- }
- }
-
- pub fn check_read(&self, filename: &str) -> DenoResult<()> {
- match self.allow_read.get_state() {
- PermissionAccessorState::Allow => Ok(()),
- PermissionAccessorState::Ask => match self
- .try_permissions_prompt(&format!("read access to \"{}\"", filename))
- {
- Err(e) => Err(e),
- Ok(v) => {
- self.allow_read.update_with_prompt_result(&v);
- v.check()?;
- Ok(())
- }
- },
- PermissionAccessorState::Deny => Err(permission_denied()),
- }
- }
-
- pub fn check_write(&self, filename: &str) -> DenoResult<()> {
- match self.allow_write.get_state() {
- PermissionAccessorState::Allow => Ok(()),
- PermissionAccessorState::Ask => match self
- .try_permissions_prompt(&format!("write access to \"{}\"", filename))
- {
- Err(e) => Err(e),
- Ok(v) => {
- self.allow_write.update_with_prompt_result(&v);
- v.check()?;
- Ok(())
- }
- },
- PermissionAccessorState::Deny => Err(permission_denied()),
- }
- }
-
- pub fn check_net(&self, domain_name: &str) -> DenoResult<()> {
- match self.allow_net.get_state() {
- PermissionAccessorState::Allow => Ok(()),
- PermissionAccessorState::Ask => match self.try_permissions_prompt(
- &format!("network access to \"{}\"", domain_name),
- ) {
- Err(e) => Err(e),
- Ok(v) => {
- self.allow_net.update_with_prompt_result(&v);
- v.check()?;
- Ok(())
- }
- },
- PermissionAccessorState::Deny => Err(permission_denied()),
- }
- }
-
- pub fn check_env(&self) -> DenoResult<()> {
- match self.allow_env.get_state() {
- PermissionAccessorState::Allow => Ok(()),
- PermissionAccessorState::Ask => {
- match self.try_permissions_prompt("access to environment variables") {
- Err(e) => Err(e),
- Ok(v) => {
- self.allow_env.update_with_prompt_result(&v);
- v.check()?;
- Ok(())
- }
- }
- }
- PermissionAccessorState::Deny => Err(permission_denied()),
- }
- }
-
- /// Try to present the user with a permission prompt
- /// will error with permission_denied if no_prompts is enabled
- fn try_permissions_prompt(&self, message: &str) -> DenoResult<PromptResult> {
- if self.no_prompts.load(Ordering::SeqCst) {
- return Err(permission_denied());
- }
- if !atty::is(atty::Stream::Stdin) || !atty::is(atty::Stream::Stderr) {
- return Err(permission_denied());
- };
- permission_prompt(message)
- }
-
- pub fn allows_run(&self) -> bool {
- return self.allow_run.is_allow();
- }
-
- pub fn allows_read(&self) -> bool {
- return self.allow_read.is_allow();
- }
-
- pub fn allows_write(&self) -> bool {
- return self.allow_write.is_allow();
- }
-
- pub fn allows_net(&self) -> bool {
- return self.allow_net.is_allow();
- }
-
- pub fn allows_env(&self) -> bool {
- return self.allow_env.is_allow();
- }
-
- pub fn revoke_run(&self) -> DenoResult<()> {
- self.allow_run.revoke();
- return Ok(());
- }
-
- pub fn revoke_read(&self) -> DenoResult<()> {
- self.allow_read.revoke();
- return Ok(());
- }
-
- pub fn revoke_write(&self) -> DenoResult<()> {
- self.allow_write.revoke();
- return Ok(());
- }
-
- pub fn revoke_net(&self) -> DenoResult<()> {
- self.allow_net.revoke();
- return Ok(());
- }
-
- pub fn revoke_env(&self) -> DenoResult<()> {
- self.allow_env.revoke();
- return Ok(());
- }
-}
-
-/// Quad-state value for representing user input on permission prompt
-#[derive(Debug, Clone)]
-pub enum PromptResult {
- AllowAlways = 0,
- AllowOnce = 1,
- DenyOnce = 2,
- DenyAlways = 3,
-}
-
-impl PromptResult {
- /// If value is any form of deny this will error with permission_denied
- pub fn check(&self) -> DenoResult<()> {
- match self {
- PromptResult::DenyOnce => Err(permission_denied()),
- PromptResult::DenyAlways => Err(permission_denied()),
- _ => Ok(()),
- }
- }
-}
-
-impl fmt::Display for PromptResult {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- PromptResult::AllowAlways => f.pad("AllowAlways"),
- PromptResult::AllowOnce => f.pad("AllowOnce"),
- PromptResult::DenyOnce => f.pad("DenyOnce"),
- PromptResult::DenyAlways => f.pad("DenyAlways"),
- }
- }
-}
-
-fn permission_prompt(message: &str) -> DenoResult<PromptResult> {
- let msg = format!("⚠️ Deno requests {}. Grant? [a/y/n/d (a = allow always, y = allow once, n = deny once, d = deny always)] ", message);
- // print to stderr so that if deno is > to a file this is still displayed.
- eprint!("{}", Style::new().bold().paint(msg));
- loop {
- let mut input = String::new();
- let stdin = io::stdin();
- let _nread = stdin.read_line(&mut input)?;
- let ch = input.chars().next().unwrap();
- match ch.to_ascii_lowercase() {
- 'a' => return Ok(PromptResult::AllowAlways),
- 'y' => return Ok(PromptResult::AllowOnce),
- 'n' => return Ok(PromptResult::DenyOnce),
- 'd' => return Ok(PromptResult::DenyAlways),
- _ => {
- // If we don't get a recognized option try again.
- let msg_again = format!("Unrecognized option '{}' [a/y/n/d (a = allow always, y = allow once, n = deny once, d = deny always)] ", ch);
- eprint!("{}", Style::new().bold().paint(msg_again));
- }
- };
- }
-}
diff --git a/src/repl.rs b/src/repl.rs
deleted file mode 100644
index 55bf4a114..000000000
--- a/src/repl.rs
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-use rustyline;
-
-use crate::msg::ErrorKind;
-use std::error::Error;
-
-use crate::deno_dir::DenoDir;
-use crate::errors::new as deno_error;
-use crate::errors::DenoResult;
-use std::path::PathBuf;
-
-#[cfg(not(windows))]
-use rustyline::Editor;
-
-// Work around the issue that on Windows, `struct Editor` does not implement the
-// `Send` trait, because it embeds a windows HANDLE which is a type alias for
-// *mut c_void. This value isn't actually a pointer and there's nothing that
-// can be mutated through it, so hack around it. TODO: a prettier solution.
-#[cfg(windows)]
-use std::ops::{Deref, DerefMut};
-
-#[cfg(windows)]
-struct Editor<T: rustyline::Helper> {
- inner: rustyline::Editor<T>,
-}
-
-#[cfg(windows)]
-unsafe impl<T: rustyline::Helper> Send for Editor<T> {}
-
-#[cfg(windows)]
-impl<T: rustyline::Helper> Editor<T> {
- pub fn new() -> Editor<T> {
- Editor {
- inner: rustyline::Editor::<T>::new(),
- }
- }
-}
-
-#[cfg(windows)]
-impl<T: rustyline::Helper> Deref for Editor<T> {
- type Target = rustyline::Editor<T>;
-
- fn deref(&self) -> &rustyline::Editor<T> {
- &self.inner
- }
-}
-
-#[cfg(windows)]
-impl<T: rustyline::Helper> DerefMut for Editor<T> {
- fn deref_mut(&mut self) -> &mut rustyline::Editor<T> {
- &mut self.inner
- }
-}
-
-pub struct Repl {
- editor: Editor<()>,
- history_file: PathBuf,
-}
-
-impl Repl {
- pub fn new(history_file: PathBuf) -> Self {
- let mut repl = Self {
- editor: Editor::<()>::new(),
- history_file,
- };
-
- repl.load_history();
- repl
- }
-
- fn load_history(&mut self) {
- debug!("Loading REPL history: {:?}", self.history_file);
- self
- .editor
- .load_history(&self.history_file.to_str().unwrap())
- .map_err(|e| debug!("Unable to load history file: {:?} {}", self.history_file, e))
- // ignore this error (e.g. it occurs on first load)
- .unwrap_or(())
- }
-
- fn save_history(&mut self) -> DenoResult<()> {
- self
- .editor
- .save_history(&self.history_file.to_str().unwrap())
- .map(|_| debug!("Saved REPL history to: {:?}", self.history_file))
- .map_err(|e| {
- eprintln!("Unable to save REPL history: {:?} {}", self.history_file, e);
- deno_error(ErrorKind::Other, e.description().to_string())
- })
- }
-
- pub fn readline(&mut self, prompt: &str) -> DenoResult<String> {
- self
- .editor
- .readline(&prompt)
- .map(|line| {
- self.editor.add_history_entry(line.as_ref());
- line
- }).map_err(|e| deno_error(ErrorKind::Other, e.description().to_string()))
- // Forward error to TS side for processing
- }
-}
-
-impl Drop for Repl {
- fn drop(&mut self) {
- self.save_history().unwrap();
- }
-}
-
-pub fn history_path(dir: &DenoDir, history_file: &str) -> PathBuf {
- let mut p: PathBuf = dir.root.clone();
- p.push(history_file);
- p
-}
diff --git a/src/resolve_addr.rs b/src/resolve_addr.rs
deleted file mode 100644
index f26655be1..000000000
--- a/src/resolve_addr.rs
+++ /dev/null
@@ -1,156 +0,0 @@
-// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-
-use futures::Async;
-use futures::Future;
-use futures::Poll;
-use std::error::Error;
-use std::fmt;
-use std::net::SocketAddr;
-use std::net::ToSocketAddrs;
-
-/// Go-style network address parsing. Returns a future.
-/// Examples:
-/// "192.0.2.1:25"
-/// ":80"
-/// "[2001:db8::1]:80"
-/// "198.51.100.1:80"
-/// "deno.land:443"
-pub fn resolve_addr(address: &str) -> ResolveAddrFuture {
- ResolveAddrFuture {
- address: address.to_string(),
- }
-}
-
-#[derive(Debug)]
-pub enum ResolveAddrError {
- Syntax,
- Resolution(std::io::Error),
-}
-
-impl fmt::Display for ResolveAddrError {
- fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- fmt.write_str(self.description())
- }
-}
-
-impl Error for ResolveAddrError {
- fn description(&self) -> &str {
- match self {
- ResolveAddrError::Syntax => "invalid address syntax",
- ResolveAddrError::Resolution(e) => e.description(),
- }
- }
-}
-
-pub struct ResolveAddrFuture {
- address: String,
-}
-
-impl Future for ResolveAddrFuture {
- type Item = SocketAddr;
- type Error = ResolveAddrError;
-
- fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
- // The implementation of this is not actually async at the moment,
- // however we intend to use async DNS resolution in the future and
- // so we expose this as a future instead of Result.
- match split(&self.address) {
- None => Err(ResolveAddrError::Syntax),
- Some(addr_port_pair) => {
- // I absolutely despise the .to_socket_addrs() API.
- let r = addr_port_pair
- .to_socket_addrs()
- .map_err(ResolveAddrError::Resolution);
-
- r.and_then(|mut iter| match iter.next() {
- Some(a) => Ok(Async::Ready(a)),
- None => panic!("There should be at least one result"),
- })
- }
- }
- }
-}
-
-fn split(address: &str) -> Option<(&str, u16)> {
- address.rfind(':').and_then(|i| {
- let (a, p) = address.split_at(i);
- // Default to localhost if given just the port. Example: ":80"
- let addr = if !a.is_empty() { a } else { "0.0.0.0" };
- // If this looks like an ipv6 IP address. Example: "[2001:db8::1]"
- // Then we remove the brackets.
- let addr = if addr.starts_with('[') && addr.ends_with(']') {
- let l = addr.len() - 1;
- addr.get(1..l).unwrap()
- } else {
- addr
- };
-
- let p = p.trim_start_matches(':');
- match p.parse::<u16>() {
- Err(_) => None,
- Ok(port) => Some((addr, port)),
- }
- })
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use std::net::Ipv4Addr;
- use std::net::Ipv6Addr;
- use std::net::SocketAddrV4;
- use std::net::SocketAddrV6;
-
- #[test]
- fn split1() {
- assert_eq!(split("127.0.0.1:80"), Some(("127.0.0.1", 80)));
- }
-
- #[test]
- fn split2() {
- assert_eq!(split(":80"), Some(("0.0.0.0", 80)));
- }
-
- #[test]
- fn split3() {
- assert_eq!(split("no colon"), None);
- }
-
- #[test]
- fn split4() {
- assert_eq!(split("deno.land:443"), Some(("deno.land", 443)));
- }
-
- #[test]
- fn split5() {
- assert_eq!(split("[2001:db8::1]:8080"), Some(("2001:db8::1", 8080)));
- }
-
- #[test]
- fn resolve_addr1() {
- let expected =
- SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 80));
- let actual = resolve_addr("127.0.0.1:80").wait().unwrap();
- assert_eq!(actual, expected);
- }
-
- #[test]
- fn resolve_addr3() {
- let expected =
- SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(192, 0, 2, 1), 25));
- let actual = resolve_addr("192.0.2.1:25").wait().unwrap();
- assert_eq!(actual, expected);
- }
-
- #[test]
- fn resolve_addr_ipv6() {
- let expected = SocketAddr::V6(SocketAddrV6::new(
- Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1),
- 8080,
- 0,
- 0,
- ));
- let actual = resolve_addr("[2001:db8::1]:8080").wait().unwrap();
- assert_eq!(actual, expected);
- }
-}
diff --git a/src/resources.rs b/src/resources.rs
deleted file mode 100644
index 1540f4ff7..000000000
--- a/src/resources.rs
+++ /dev/null
@@ -1,494 +0,0 @@
-// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-
-// Think of Resources as File Descriptors. They are integers that are allocated
-// by the privileged side of Deno to refer to various resources. The simplest
-// example are standard file system files and stdio - but there will be other
-// resources added in the future that might not correspond to operating system
-// level File Descriptors. To avoid confusion we call them "resources" not "file
-// descriptors". This module implements a global resource table. Ops (AKA
-// handlers) look up resources by their integer id here.
-
-use crate::cli::Buf;
-use crate::errors;
-use crate::errors::bad_resource;
-use crate::errors::DenoError;
-use crate::errors::DenoResult;
-use crate::http_body::HttpBody;
-use crate::isolate_state::WorkerChannels;
-use crate::repl::Repl;
-
-use futures;
-use futures::Future;
-use futures::Poll;
-use futures::Sink;
-use futures::Stream;
-use hyper;
-use std;
-use std::collections::HashMap;
-use std::io::{Error, Read, Seek, SeekFrom, Write};
-use std::net::{Shutdown, SocketAddr};
-use std::process::ExitStatus;
-use std::sync::atomic::AtomicUsize;
-use std::sync::atomic::Ordering;
-use std::sync::{Arc, Mutex};
-use tokio;
-use tokio::io::{AsyncRead, AsyncWrite};
-use tokio::net::TcpStream;
-use tokio_process;
-
-pub type ResourceId = u32; // Sometimes referred to RID.
-
-// These store Deno's file descriptors. These are not necessarily the operating
-// system ones.
-type ResourceTable = HashMap<ResourceId, Repr>;
-
-#[cfg(not(windows))]
-use std::os::unix::io::FromRawFd;
-
-#[cfg(windows)]
-use std::os::windows::io::FromRawHandle;
-
-#[cfg(windows)]
-extern crate winapi;
-
-lazy_static! {
- // Starts at 3 because stdio is [0-2].
- static ref NEXT_RID: AtomicUsize = AtomicUsize::new(3);
- static ref RESOURCE_TABLE: Mutex<ResourceTable> = Mutex::new({
- let mut m = HashMap::new();
- // TODO Load these lazily during lookup?
- m.insert(0, Repr::Stdin(tokio::io::stdin()));
-
- m.insert(1, Repr::Stdout({
- #[cfg(not(windows))]
- let stdout = unsafe { std::fs::File::from_raw_fd(1) };
- #[cfg(windows)]
- let stdout = unsafe {
- std::fs::File::from_raw_handle(winapi::um::processenv::GetStdHandle(
- winapi::um::winbase::STD_OUTPUT_HANDLE))
- };
- tokio::fs::File::from_std(stdout)
- }));
-
- m.insert(2, Repr::Stderr(tokio::io::stderr()));
- m
- });
-}
-
-// Internal representation of Resource.
-enum Repr {
- Stdin(tokio::io::Stdin),
- Stdout(tokio::fs::File),
- Stderr(tokio::io::Stderr),
- FsFile(tokio::fs::File),
- // Since TcpListener might be closed while there is a pending accept task,
- // we need to track the task so that when the listener is closed,
- // this pending task could be notified and die.
- // Currently TcpListener itself does not take care of this issue.
- // See: https://github.com/tokio-rs/tokio/issues/846
- TcpListener(tokio::net::TcpListener, Option<futures::task::Task>),
- TcpStream(tokio::net::TcpStream),
- HttpBody(HttpBody),
- Repl(Arc<Mutex<Repl>>),
- // Enum size is bounded by the largest variant.
- // Use `Box` around large `Child` struct.
- // https://rust-lang.github.io/rust-clippy/master/index.html#large_enum_variant
- Child(Box<tokio_process::Child>),
- ChildStdin(tokio_process::ChildStdin),
- ChildStdout(tokio_process::ChildStdout),
- ChildStderr(tokio_process::ChildStderr),
- Worker(WorkerChannels),
-}
-
-/// If the given rid is open, this returns the type of resource, E.G. "worker".
-/// If the rid is closed or was never open, it returns None.
-pub fn get_type(rid: ResourceId) -> Option<String> {
- let table = RESOURCE_TABLE.lock().unwrap();
- table.get(&rid).map(inspect_repr)
-}
-
-pub fn table_entries() -> Vec<(u32, String)> {
- let table = RESOURCE_TABLE.lock().unwrap();
-
- table
- .iter()
- .map(|(key, value)| (*key, inspect_repr(&value)))
- .collect()
-}
-
-#[test]
-fn test_table_entries() {
- let mut entries = table_entries();
- entries.sort();
- assert_eq!(entries[0], (0, String::from("stdin")));
- assert_eq!(entries[1], (1, String::from("stdout")));
- assert_eq!(entries[2], (2, String::from("stderr")));
-}
-
-fn inspect_repr(repr: &Repr) -> String {
- let h_repr = match repr {
- Repr::Stdin(_) => "stdin",
- Repr::Stdout(_) => "stdout",
- Repr::Stderr(_) => "stderr",
- Repr::FsFile(_) => "fsFile",
- Repr::TcpListener(_, _) => "tcpListener",
- Repr::TcpStream(_) => "tcpStream",
- Repr::HttpBody(_) => "httpBody",
- Repr::Repl(_) => "repl",
- Repr::Child(_) => "child",
- Repr::ChildStdin(_) => "childStdin",
- Repr::ChildStdout(_) => "childStdout",
- Repr::ChildStderr(_) => "childStderr",
- Repr::Worker(_) => "worker",
- };
-
- String::from(h_repr)
-}
-
-// Abstract async file interface.
-// Ideally in unix, if Resource represents an OS rid, it will be the same.
-#[derive(Clone, Debug)]
-pub struct Resource {
- pub rid: ResourceId,
-}
-
-impl Resource {
- // TODO Should it return a Resource instead of net::TcpStream?
- pub fn poll_accept(&mut self) -> Poll<(TcpStream, SocketAddr), Error> {
- let mut table = RESOURCE_TABLE.lock().unwrap();
- let maybe_repr = table.get_mut(&self.rid);
- match maybe_repr {
- None => Err(std::io::Error::new(
- std::io::ErrorKind::Other,
- "Listener has been closed",
- )),
- Some(repr) => match repr {
- Repr::TcpListener(ref mut s, _) => s.poll_accept(),
- _ => panic!("Cannot accept"),
- },
- }
- }
-
- // close(2) is done by dropping the value. Therefore we just need to remove
- // the resource from the RESOURCE_TABLE.
- pub fn close(&self) {
- let mut table = RESOURCE_TABLE.lock().unwrap();
- let r = table.remove(&self.rid);
- assert!(r.is_some());
- }
-
- pub fn shutdown(&mut self, how: Shutdown) -> Result<(), DenoError> {
- let mut table = RESOURCE_TABLE.lock().unwrap();
- let maybe_repr = table.get_mut(&self.rid);
- match maybe_repr {
- None => panic!("bad rid"),
- Some(repr) => match repr {
- Repr::TcpStream(ref mut f) => {
- TcpStream::shutdown(f, how).map_err(DenoError::from)
- }
- _ => panic!("Cannot shutdown"),
- },
- }
- }
-}
-
-impl Read for Resource {
- fn read(&mut self, _buf: &mut [u8]) -> std::io::Result<usize> {
- unimplemented!();
- }
-}
-
-impl AsyncRead for Resource {
- fn poll_read(&mut self, buf: &mut [u8]) -> Poll<usize, Error> {
- let mut table = RESOURCE_TABLE.lock().unwrap();
- let maybe_repr = table.get_mut(&self.rid);
- match maybe_repr {
- None => panic!("bad rid"),
- Some(repr) => match repr {
- Repr::FsFile(ref mut f) => f.poll_read(buf),
- Repr::Stdin(ref mut f) => f.poll_read(buf),
- Repr::TcpStream(ref mut f) => f.poll_read(buf),
- Repr::HttpBody(ref mut f) => f.poll_read(buf),
- Repr::ChildStdout(ref mut f) => f.poll_read(buf),
- Repr::ChildStderr(ref mut f) => f.poll_read(buf),
- _ => panic!("Cannot read"),
- },
- }
- }
-}
-
-impl Write for Resource {
- fn write(&mut self, _buf: &[u8]) -> std::io::Result<usize> {
- unimplemented!()
- }
-
- fn flush(&mut self) -> std::io::Result<()> {
- unimplemented!()
- }
-}
-
-impl AsyncWrite for Resource {
- fn poll_write(&mut self, buf: &[u8]) -> Poll<usize, Error> {
- let mut table = RESOURCE_TABLE.lock().unwrap();
- let maybe_repr = table.get_mut(&self.rid);
- match maybe_repr {
- None => panic!("bad rid"),
- Some(repr) => match repr {
- Repr::FsFile(ref mut f) => f.poll_write(buf),
- Repr::Stdout(ref mut f) => f.poll_write(buf),
- Repr::Stderr(ref mut f) => f.poll_write(buf),
- Repr::TcpStream(ref mut f) => f.poll_write(buf),
- Repr::ChildStdin(ref mut f) => f.poll_write(buf),
- _ => panic!("Cannot write"),
- },
- }
- }
-
- fn shutdown(&mut self) -> futures::Poll<(), std::io::Error> {
- unimplemented!()
- }
-}
-
-fn new_rid() -> ResourceId {
- let next_rid = NEXT_RID.fetch_add(1, Ordering::SeqCst);
- next_rid as ResourceId
-}
-
-pub fn add_fs_file(fs_file: tokio::fs::File) -> Resource {
- let rid = new_rid();
- let mut tg = RESOURCE_TABLE.lock().unwrap();
- match tg.insert(rid, Repr::FsFile(fs_file)) {
- Some(_) => panic!("There is already a file with that rid"),
- None => Resource { rid },
- }
-}
-
-pub fn add_tcp_listener(listener: tokio::net::TcpListener) -> Resource {
- let rid = new_rid();
- let mut tg = RESOURCE_TABLE.lock().unwrap();
- let r = tg.insert(rid, Repr::TcpListener(listener, None));
- assert!(r.is_none());
- Resource { rid }
-}
-
-pub fn add_tcp_stream(stream: tokio::net::TcpStream) -> Resource {
- let rid = new_rid();
- let mut tg = RESOURCE_TABLE.lock().unwrap();
- let r = tg.insert(rid, Repr::TcpStream(stream));
- assert!(r.is_none());
- Resource { rid }
-}
-
-pub fn add_hyper_body(body: hyper::Body) -> Resource {
- let rid = new_rid();
- let mut tg = RESOURCE_TABLE.lock().unwrap();
- let body = HttpBody::from(body);
- let r = tg.insert(rid, Repr::HttpBody(body));
- assert!(r.is_none());
- Resource { rid }
-}
-
-pub fn add_repl(repl: Repl) -> Resource {
- let rid = new_rid();
- let mut tg = RESOURCE_TABLE.lock().unwrap();
- let r = tg.insert(rid, Repr::Repl(Arc::new(Mutex::new(repl))));
- assert!(r.is_none());
- Resource { rid }
-}
-
-pub fn add_worker(wc: WorkerChannels) -> Resource {
- let rid = new_rid();
- let mut tg = RESOURCE_TABLE.lock().unwrap();
- let r = tg.insert(rid, Repr::Worker(wc));
- assert!(r.is_none());
- Resource { rid }
-}
-
-pub fn worker_post_message(
- rid: ResourceId,
- buf: Buf,
-) -> futures::sink::Send<futures::sync::mpsc::Sender<Buf>> {
- let mut table = RESOURCE_TABLE.lock().unwrap();
- let maybe_repr = table.get_mut(&rid);
- match maybe_repr {
- Some(Repr::Worker(ref mut wc)) => {
- // unwrap here is incorrect, but doing it anyway
- wc.0.clone().send(buf)
- }
- _ => panic!("bad resource"), // futures::future::err(bad_resource()).into(),
- }
-}
-
-pub struct WorkerReceiver {
- rid: ResourceId,
-}
-
-// Invert the dumbness that tokio_process causes by making Child itself a future.
-impl Future for WorkerReceiver {
- type Item = Option<Buf>;
- type Error = DenoError;
-
- fn poll(&mut self) -> Poll<Option<Buf>, DenoError> {
- let mut table = RESOURCE_TABLE.lock().unwrap();
- let maybe_repr = table.get_mut(&self.rid);
- match maybe_repr {
- Some(Repr::Worker(ref mut wc)) => wc.1.poll().map_err(|()| {
- errors::new(errors::ErrorKind::Other, "recv msg error".to_string())
- }),
- _ => Err(bad_resource()),
- }
- }
-}
-
-pub fn worker_recv_message(rid: ResourceId) -> WorkerReceiver {
- WorkerReceiver { rid }
-}
-
-#[cfg_attr(feature = "cargo-clippy", allow(stutter))]
-pub struct ChildResources {
- pub child_rid: ResourceId,
- pub stdin_rid: Option<ResourceId>,
- pub stdout_rid: Option<ResourceId>,
- pub stderr_rid: Option<ResourceId>,
-}
-
-pub fn add_child(mut c: tokio_process::Child) -> ChildResources {
- let child_rid = new_rid();
- let mut tg = RESOURCE_TABLE.lock().unwrap();
-
- let mut resources = ChildResources {
- child_rid,
- stdin_rid: None,
- stdout_rid: None,
- stderr_rid: None,
- };
-
- if c.stdin().is_some() {
- let stdin = c.stdin().take().unwrap();
- let rid = new_rid();
- let r = tg.insert(rid, Repr::ChildStdin(stdin));
- assert!(r.is_none());
- resources.stdin_rid = Some(rid);
- }
- if c.stdout().is_some() {
- let stdout = c.stdout().take().unwrap();
- let rid = new_rid();
- let r = tg.insert(rid, Repr::ChildStdout(stdout));
- assert!(r.is_none());
- resources.stdout_rid = Some(rid);
- }
- if c.stderr().is_some() {
- let stderr = c.stderr().take().unwrap();
- let rid = new_rid();
- let r = tg.insert(rid, Repr::ChildStderr(stderr));
- assert!(r.is_none());
- resources.stderr_rid = Some(rid);
- }
-
- let r = tg.insert(child_rid, Repr::Child(Box::new(c)));
- assert!(r.is_none());
-
- resources
-}
-
-pub struct ChildStatus {
- rid: ResourceId,
-}
-
-// Invert the dumbness that tokio_process causes by making Child itself a future.
-impl Future for ChildStatus {
- type Item = ExitStatus;
- type Error = DenoError;
-
- fn poll(&mut self) -> Poll<ExitStatus, DenoError> {
- let mut table = RESOURCE_TABLE.lock().unwrap();
- let maybe_repr = table.get_mut(&self.rid);
- match maybe_repr {
- Some(Repr::Child(ref mut child)) => child.poll().map_err(DenoError::from),
- _ => Err(bad_resource()),
- }
- }
-}
-
-pub fn child_status(rid: ResourceId) -> DenoResult<ChildStatus> {
- let mut table = RESOURCE_TABLE.lock().unwrap();
- let maybe_repr = table.get_mut(&rid);
- match maybe_repr {
- Some(Repr::Child(ref mut _child)) => Ok(ChildStatus { rid }),
- _ => Err(bad_resource()),
- }
-}
-
-pub fn get_repl(rid: ResourceId) -> DenoResult<Arc<Mutex<Repl>>> {
- let mut table = RESOURCE_TABLE.lock().unwrap();
- let maybe_repr = table.get_mut(&rid);
- match maybe_repr {
- Some(Repr::Repl(ref mut r)) => Ok(r.clone()),
- _ => Err(bad_resource()),
- }
-}
-
-pub fn lookup(rid: ResourceId) -> Option<Resource> {
- debug!("resource lookup {}", rid);
- let table = RESOURCE_TABLE.lock().unwrap();
- table.get(&rid).map(|_| Resource { rid })
-}
-
-// TODO(kevinkassimo): revamp this after the following lands:
-// https://github.com/tokio-rs/tokio/pull/785
-pub fn seek(
- resource: Resource,
- offset: i32,
- whence: u32,
-) -> Box<dyn Future<Item = (), Error = DenoError> + Send> {
- let mut table = RESOURCE_TABLE.lock().unwrap();
- // We take ownership of File here.
- // It is put back below while still holding the lock.
- let maybe_repr = table.remove(&resource.rid);
- match maybe_repr {
- None => panic!("bad rid"),
- Some(Repr::FsFile(f)) => {
- let seek_from = match whence {
- 0 => SeekFrom::Start(offset as u64),
- 1 => SeekFrom::Current(offset as i64),
- 2 => SeekFrom::End(offset as i64),
- _ => {
- return Box::new(futures::future::err(errors::new(
- errors::ErrorKind::InvalidSeekMode,
- format!("Invalid seek mode: {}", whence),
- )));
- }
- };
- // Trait Clone not implemented on tokio::fs::File,
- // so convert to std File first.
- let std_file = f.into_std();
- // Create a copy and immediately put back.
- // We don't want to block other resource ops.
- // try_clone() would yield a copy containing the same
- // underlying fd, so operations on the copy would also
- // affect the one in resource table, and we don't need
- // to write back.
- let maybe_std_file_copy = std_file.try_clone();
- // Insert the entry back with the same rid.
- table.insert(
- resource.rid,
- Repr::FsFile(tokio_fs::File::from_std(std_file)),
- );
- if maybe_std_file_copy.is_err() {
- return Box::new(futures::future::err(DenoError::from(
- maybe_std_file_copy.unwrap_err(),
- )));
- }
- let mut std_file_copy = maybe_std_file_copy.unwrap();
- return Box::new(futures::future::lazy(move || {
- let result = std_file_copy
- .seek(seek_from)
- .map(|_| {
- return ();
- }).map_err(DenoError::from);
- futures::future::result(result)
- }));
- }
- _ => panic!("cannot seek"),
- }
-}
diff --git a/src/startup_data.rs b/src/startup_data.rs
deleted file mode 100644
index 29ae4db7d..000000000
--- a/src/startup_data.rs
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-use deno_core::deno_buf;
-use deno_core::{StartupData, StartupScript};
-
-pub fn deno_isolate_init() -> StartupData {
- if cfg!(feature = "no-snapshot-init") {
- debug!("Deno isolate init without snapshots.");
- #[cfg(not(feature = "check-only"))]
- let source_bytes =
- include_bytes!(concat!(env!("GN_OUT_DIR"), "/gen/bundle/main.js"));
- #[cfg(feature = "check-only")]
- let source_bytes = vec![];
-
- StartupData::Script(StartupScript {
- filename: "gen/bundle/main.js".to_string(),
- source: std::str::from_utf8(source_bytes).unwrap().to_string(),
- })
- } else {
- debug!("Deno isolate init with snapshots.");
- #[cfg(not(any(feature = "check-only", feature = "no-snapshot-init")))]
- let data =
- include_bytes!(concat!(env!("GN_OUT_DIR"), "/gen/snapshot_deno.bin"));
- #[cfg(any(feature = "check-only", feature = "no-snapshot-init"))]
- let data = vec![];
-
- unsafe {
- StartupData::Snapshot(deno_buf::from_raw_parts(data.as_ptr(), data.len()))
- }
- }
-}
-
-pub fn compiler_isolate_init() -> StartupData {
- if cfg!(feature = "no-snapshot-init") {
- debug!("Deno isolate init without snapshots.");
- #[cfg(not(feature = "check-only"))]
- let source_bytes =
- include_bytes!(concat!(env!("GN_OUT_DIR"), "/gen/bundle/compiler.js"));
- #[cfg(feature = "check-only")]
- let source_bytes = vec![];
-
- StartupData::Script(StartupScript {
- filename: "gen/bundle/compiler.js".to_string(),
- source: std::str::from_utf8(source_bytes).unwrap().to_string(),
- })
- } else {
- debug!("Deno isolate init with snapshots.");
- #[cfg(not(any(feature = "check-only", feature = "no-snapshot-init")))]
- let data =
- include_bytes!(concat!(env!("GN_OUT_DIR"), "/gen/snapshot_compiler.bin"));
- #[cfg(any(feature = "check-only", feature = "no-snapshot-init"))]
- let data = vec![];
-
- unsafe {
- StartupData::Snapshot(deno_buf::from_raw_parts(data.as_ptr(), data.len()))
- }
- }
-}
diff --git a/src/tokio_util.rs b/src/tokio_util.rs
deleted file mode 100644
index 810b826b4..000000000
--- a/src/tokio_util.rs
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-use crate::resources::Resource;
-use futures;
-use futures::Future;
-use futures::Poll;
-use std::io;
-use std::mem;
-use std::net::SocketAddr;
-use tokio;
-use tokio::net::TcpStream;
-
-pub fn run<F>(future: F)
-where
- F: Future<Item = (), Error = ()> + Send + 'static,
-{
- // tokio::runtime::current_thread::run(future)
- tokio::run(future)
-}
-
-pub fn block_on<F, R, E>(future: F) -> Result<R, E>
-where
- F: Send + 'static + Future<Item = R, Error = E>,
- R: Send + 'static,
- E: Send + 'static,
-{
- let (tx, rx) = futures::sync::oneshot::channel();
- tokio::spawn(future.then(move |r| tx.send(r).map_err(|_| unreachable!())));
- rx.wait().unwrap()
-}
-
-// Set the default executor so we can use tokio::spawn(). It's difficult to
-// pass around mut references to the runtime, so using with_default is
-// preferable. Ideally Tokio would provide this function.
-#[cfg(test)]
-pub fn init<F>(f: F)
-where
- F: FnOnce(),
-{
- use tokio_executor;
- let rt = tokio::runtime::Runtime::new().unwrap();
- let mut executor = rt.executor();
- let mut enter = tokio_executor::enter().expect("Multiple executors at once");
- tokio_executor::with_default(&mut executor, &mut enter, move |_enter| f());
-}
-
-#[derive(Debug)]
-enum AcceptState {
- Pending(Resource),
- Empty,
-}
-
-/// Simply accepts a connection.
-pub fn accept(r: Resource) -> Accept {
- Accept {
- state: AcceptState::Pending(r),
- }
-}
-
-/// A future which can be used to easily read available number of bytes to fill
-/// a buffer.
-///
-/// Created by the [`read`] function.
-#[derive(Debug)]
-pub struct Accept {
- state: AcceptState,
-}
-
-impl Future for Accept {
- type Item = (TcpStream, SocketAddr);
- type Error = io::Error;
-
- fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
- let (stream, addr) = match self.state {
- AcceptState::Pending(ref mut r) => try_ready!(r.poll_accept()),
- AcceptState::Empty => panic!("poll Accept after it's done"),
- };
-
- match mem::replace(&mut self.state, AcceptState::Empty) {
- AcceptState::Pending(_) => Ok((stream, addr).into()),
- AcceptState::Empty => panic!("invalid internal state"),
- }
- }
-}
-
-/// `futures::future::poll_fn` only support `F: FnMut()->Poll<T, E>`
-/// However, we require that `F: FnOnce()->Poll<T, E>`.
-/// Therefore, we created our version of `poll_fn`.
-pub fn poll_fn<T, E, F>(f: F) -> PollFn<F>
-where
- F: FnOnce() -> Poll<T, E>,
-{
- PollFn { inner: Some(f) }
-}
-
-pub struct PollFn<F> {
- inner: Option<F>,
-}
-
-impl<T, E, F> Future for PollFn<F>
-where
- F: FnOnce() -> Poll<T, E>,
-{
- type Item = T;
- type Error = E;
-
- fn poll(&mut self) -> Poll<T, E> {
- let f = self.inner.take().expect("Inner fn has been taken.");
- f()
- }
-}
-
-pub fn panic_on_error<I, E, F>(f: F) -> impl Future<Item = I, Error = ()>
-where
- F: Future<Item = I, Error = E>,
- E: std::fmt::Debug,
-{
- f.map_err(|err| panic!("Future got unexpected error: {:?}", err))
-}
diff --git a/src/tokio_write.rs b/src/tokio_write.rs
deleted file mode 100644
index 945de375d..000000000
--- a/src/tokio_write.rs
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-// TODO Submit this file upstream into tokio-io/src/io/write.rs
-use std::io;
-use std::mem;
-
-use futures::{Future, Poll};
-use tokio::io::AsyncWrite;
-
-/// A future used to write some data to a stream.
-///
-/// This is created by the [`write`] top-level method.
-///
-/// [`write`]: fn.write.html
-#[derive(Debug)]
-pub struct Write<A, T> {
- state: State<A, T>,
-}
-
-#[derive(Debug)]
-enum State<A, T> {
- Pending { a: A, buf: T },
- Empty,
-}
-
-/// Creates a future that will write some of the buffer `buf` to
-/// the stream `a` provided.
-///
-/// Any error which happens during writing will cause both the stream and the
-/// buffer to get destroyed.
-pub fn write<A, T>(a: A, buf: T) -> Write<A, T>
-where
- A: AsyncWrite,
- T: AsRef<[u8]>,
-{
- Write {
- state: State::Pending { a, buf },
- }
-}
-
-impl<A, T> Future for Write<A, T>
-where
- A: AsyncWrite,
- T: AsRef<[u8]>,
-{
- type Item = (A, T, usize);
- type Error = io::Error;
-
- fn poll(&mut self) -> Poll<(A, T, usize), io::Error> {
- let nwritten = match self.state {
- State::Pending {
- ref mut a,
- ref mut buf,
- } => try_ready!(a.poll_write(buf.as_ref())),
- State::Empty => panic!("poll a Read after it's done"),
- };
-
- match mem::replace(&mut self.state, State::Empty) {
- State::Pending { a, buf } => Ok((a, buf, nwritten).into()),
- State::Empty => panic!("invalid internal state"),
- }
- }
-}
diff --git a/src/version.rs b/src/version.rs
deleted file mode 100644
index e6ec9008b..000000000
--- a/src/version.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-pub const DENO: &str = env!("CARGO_PKG_VERSION");
-
-pub fn v8() -> &'static str {
- deno_core::v8_version()
-}
diff --git a/src/workers.rs b/src/workers.rs
deleted file mode 100644
index edded7756..000000000
--- a/src/workers.rs
+++ /dev/null
@@ -1,181 +0,0 @@
-// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-use crate::cli::Buf;
-use crate::cli::Cli;
-use crate::flags::DenoFlags;
-use crate::isolate::Isolate;
-use crate::isolate_state::IsolateState;
-use crate::isolate_state::WorkerChannels;
-use crate::js_errors::JSErrorColor;
-use crate::permissions::DenoPermissions;
-use crate::resources;
-use crate::tokio_util;
-use deno_core::JSError;
-use deno_core::StartupData;
-use futures::future::lazy;
-use futures::sync::mpsc;
-use futures::sync::oneshot;
-use futures::Future;
-use futures::Poll;
-use std::sync::Arc;
-use std::thread;
-
-/// Rust interface for WebWorkers.
-pub struct Worker {
- isolate: Isolate,
-}
-
-impl Worker {
- pub fn new(
- startup_data: Option<StartupData>,
- flags: DenoFlags,
- argv: Vec<String>,
- permissions: DenoPermissions,
- ) -> (Self, WorkerChannels) {
- let (worker_in_tx, worker_in_rx) = mpsc::channel::<Buf>(1);
- let (worker_out_tx, worker_out_rx) = mpsc::channel::<Buf>(1);
-
- let internal_channels = (worker_out_tx, worker_in_rx);
- let external_channels = (worker_in_tx, worker_out_rx);
-
- let state =
- Arc::new(IsolateState::new(flags, argv, Some(internal_channels)));
-
- let cli = Cli::new(startup_data, state, permissions);
- let isolate = Isolate::new(cli);
-
- let worker = Worker { isolate };
- (worker, external_channels)
- }
-
- pub fn execute(&mut self, js_source: &str) -> Result<(), JSError> {
- self.isolate.execute(js_source)
- }
-}
-
-impl Future for Worker {
- type Item = ();
- type Error = JSError;
-
- fn poll(&mut self) -> Poll<(), JSError> {
- self.isolate.poll()
- }
-}
-
-pub fn spawn(
- startup_data: Option<StartupData>,
- state: &IsolateState,
- js_source: String,
- permissions: DenoPermissions,
-) -> resources::Resource {
- // TODO This function should return a Future, so that the caller can retrieve
- // the JSError if one is thrown. Currently it just prints to stderr and calls
- // exit(1).
- // let (js_error_tx, js_error_rx) = oneshot::channel::<JSError>();
- let (p, c) = oneshot::channel::<resources::Resource>();
- let builder = thread::Builder::new().name("worker".to_string());
-
- let flags = state.flags.clone();
- let argv = state.argv.clone();
-
- let _tid = builder
- .spawn(move || {
- tokio_util::run(lazy(move || {
- let (mut worker, external_channels) =
- Worker::new(startup_data, flags, argv, permissions);
- let resource = resources::add_worker(external_channels);
- p.send(resource.clone()).unwrap();
-
- worker
- .execute("denoMain()")
- .expect("worker denoMain failed");
- worker
- .execute("workerMain()")
- .expect("worker workerMain failed");
- worker.execute(&js_source).expect("worker js_source failed");
-
- worker.then(move |r| -> Result<(), ()> {
- resource.close();
- debug!("workers.rs after resource close");
- if let Err(err) = r {
- eprintln!("{}", JSErrorColor(&err).to_string());
- std::process::exit(1);
- }
- Ok(())
- })
- }));
-
- debug!("workers.rs after spawn");
- }).unwrap();
-
- c.wait().unwrap()
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use crate::startup_data;
-
- #[test]
- fn test_spawn() {
- let startup_data = startup_data::compiler_isolate_init();
- let resource = spawn(
- Some(startup_data),
- &IsolateState::mock(),
- r#"
- onmessage = function(e) {
- let s = new TextDecoder().decode(e.data);;
- console.log("msg from main script", s);
- if (s == "exit") {
- close();
- return;
- } else {
- console.assert(s === "hi");
- }
- postMessage(new Uint8Array([1, 2, 3]));
- console.log("after postMessage");
- }
- "#.into(),
- DenoPermissions::default(),
- );
- let msg = String::from("hi").into_boxed_str().into_boxed_bytes();
-
- let r = resources::worker_post_message(resource.rid, msg).wait();
- assert!(r.is_ok());
-
- let maybe_msg =
- resources::worker_recv_message(resource.rid).wait().unwrap();
- assert!(maybe_msg.is_some());
- assert_eq!(*maybe_msg.unwrap(), [1, 2, 3]);
-
- let msg = String::from("exit").into_boxed_str().into_boxed_bytes();
- let r = resources::worker_post_message(resource.rid, msg).wait();
- assert!(r.is_ok());
- }
-
- #[test]
- fn removed_from_resource_table_on_close() {
- let startup_data = startup_data::compiler_isolate_init();
- let resource = spawn(
- Some(startup_data),
- &IsolateState::mock(),
- "onmessage = () => close();".into(),
- DenoPermissions::default(),
- );
-
- assert_eq!(
- resources::get_type(resource.rid),
- Some("worker".to_string())
- );
-
- let msg = String::from("hi").into_boxed_str().into_boxed_bytes();
- let r = resources::worker_post_message(resource.rid, msg).wait();
- assert!(r.is_ok());
- println!("rid {:?}", resource.rid);
-
- // TODO Need a way to get a future for when a resource closes.
- // For now, just sleep for a bit.
- // resource.close();
- thread::sleep(std::time::Duration::from_millis(1000));
- assert_eq!(resources::get_type(resource.rid), None);
- }
-}