summaryrefslogtreecommitdiff
path: root/cli/resources.rs
diff options
context:
space:
mode:
authorRyan Dahl <ry@tinyclouds.org>2019-11-13 23:14:48 -0500
committerRy Dahl <ry@tinyclouds.org>2019-11-13 23:42:35 -0500
commitfdf0ede2acd110ba04857d5674db19c908b3ff32 (patch)
tree880252cadf6dd5024fe4d32dca7ab903af55e713 /cli/resources.rs
parentfd62379eafde6571f126df5650b80cfda9f74229 (diff)
Revert "refactor: per-worker resource table (#3306)"
This patch does not work with the recent bundler changes (#3325). Unfortunately I didn't merge master before landing this patch. It has something to do with console.log not working inside the compiler worker. This reverts commit fd62379eafde6571f126df5650b80cfda9f74229.
Diffstat (limited to 'cli/resources.rs')
-rw-r--r--cli/resources.rs209
1 files changed, 209 insertions, 0 deletions
diff --git a/cli/resources.rs b/cli/resources.rs
new file mode 100644
index 000000000..db9b43eeb
--- /dev/null
+++ b/cli/resources.rs
@@ -0,0 +1,209 @@
+// 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::deno_error::bad_resource;
+use crate::http_body::HttpBody;
+use deno::ErrBox;
+pub use deno::Resource;
+pub use deno::ResourceId;
+use deno::ResourceTable;
+
+use futures;
+use futures::Future;
+use futures::Poll;
+use reqwest::r#async::Decoder as ReqwestDecoder;
+use std;
+use std::sync::Mutex;
+use std::sync::MutexGuard;
+use tokio;
+use tokio::io::{AsyncRead, AsyncWrite};
+use tokio::net::TcpStream;
+use tokio_process;
+use tokio_rustls::client::TlsStream as ClientTlsStream;
+use tokio_rustls::server::TlsStream as ServerTlsStream;
+
+#[cfg(not(windows))]
+use std::os::unix::io::FromRawFd;
+
+#[cfg(windows)]
+use std::os::windows::io::FromRawHandle;
+
+#[cfg(windows)]
+extern crate winapi;
+
+lazy_static! {
+ static ref RESOURCE_TABLE: Mutex<ResourceTable> = Mutex::new({
+ let mut table = ResourceTable::default();
+
+ // TODO Load these lazily during lookup?
+ table.add("stdin", Box::new(CliResource::Stdin(tokio::io::stdin())));
+
+ table.add("stdout", Box::new(CliResource::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)
+ })));
+
+ table.add("stderr", Box::new(CliResource::Stderr(tokio::io::stderr())));
+ table
+ });
+}
+
+// TODO: rename to `StreamResource`
+pub enum CliResource {
+ Stdin(tokio::io::Stdin),
+ Stdout(tokio::fs::File),
+ Stderr(tokio::io::Stderr),
+ FsFile(tokio::fs::File),
+ TcpStream(tokio::net::TcpStream),
+ ServerTlsStream(Box<ServerTlsStream<TcpStream>>),
+ ClientTlsStream(Box<ClientTlsStream<TcpStream>>),
+ HttpBody(HttpBody),
+ ChildStdin(tokio_process::ChildStdin),
+ ChildStdout(tokio_process::ChildStdout),
+ ChildStderr(tokio_process::ChildStderr),
+}
+
+impl Resource for CliResource {}
+
+pub fn lock_resource_table<'a>() -> MutexGuard<'a, ResourceTable> {
+ RESOURCE_TABLE.lock().unwrap()
+}
+
+/// `DenoAsyncRead` is the same as the `tokio_io::AsyncRead` trait
+/// but uses an `ErrBox` error instead of `std::io:Error`
+pub trait DenoAsyncRead {
+ fn poll_read(&mut self, buf: &mut [u8]) -> Poll<usize, ErrBox>;
+}
+
+impl DenoAsyncRead for CliResource {
+ fn poll_read(&mut self, buf: &mut [u8]) -> Poll<usize, ErrBox> {
+ let r = match self {
+ CliResource::FsFile(ref mut f) => f.poll_read(buf),
+ CliResource::Stdin(ref mut f) => f.poll_read(buf),
+ CliResource::TcpStream(ref mut f) => f.poll_read(buf),
+ CliResource::ClientTlsStream(ref mut f) => f.poll_read(buf),
+ CliResource::ServerTlsStream(ref mut f) => f.poll_read(buf),
+ CliResource::HttpBody(ref mut f) => f.poll_read(buf),
+ CliResource::ChildStdout(ref mut f) => f.poll_read(buf),
+ CliResource::ChildStderr(ref mut f) => f.poll_read(buf),
+ _ => {
+ return Err(bad_resource());
+ }
+ };
+
+ r.map_err(ErrBox::from)
+ }
+}
+
+/// `DenoAsyncWrite` is the same as the `tokio_io::AsyncWrite` trait
+/// but uses an `ErrBox` error instead of `std::io:Error`
+pub trait DenoAsyncWrite {
+ fn poll_write(&mut self, buf: &[u8]) -> Poll<usize, ErrBox>;
+
+ fn shutdown(&mut self) -> Poll<(), ErrBox>;
+}
+
+impl DenoAsyncWrite for CliResource {
+ fn poll_write(&mut self, buf: &[u8]) -> Poll<usize, ErrBox> {
+ let r = match self {
+ CliResource::FsFile(ref mut f) => f.poll_write(buf),
+ CliResource::Stdout(ref mut f) => f.poll_write(buf),
+ CliResource::Stderr(ref mut f) => f.poll_write(buf),
+ CliResource::TcpStream(ref mut f) => f.poll_write(buf),
+ CliResource::ClientTlsStream(ref mut f) => f.poll_write(buf),
+ CliResource::ServerTlsStream(ref mut f) => f.poll_write(buf),
+ CliResource::ChildStdin(ref mut f) => f.poll_write(buf),
+ _ => {
+ return Err(bad_resource());
+ }
+ };
+
+ r.map_err(ErrBox::from)
+ }
+
+ fn shutdown(&mut self) -> futures::Poll<(), ErrBox> {
+ unimplemented!()
+ }
+}
+
+pub fn add_fs_file(fs_file: tokio::fs::File) -> ResourceId {
+ let mut table = lock_resource_table();
+ table.add("fsFile", Box::new(CliResource::FsFile(fs_file)))
+}
+
+pub fn add_tcp_stream(stream: tokio::net::TcpStream) -> ResourceId {
+ let mut table = lock_resource_table();
+ table.add("tcpStream", Box::new(CliResource::TcpStream(stream)))
+}
+
+pub fn add_tls_stream(stream: ClientTlsStream<TcpStream>) -> ResourceId {
+ let mut table = lock_resource_table();
+ table.add(
+ "clientTlsStream",
+ Box::new(CliResource::ClientTlsStream(Box::new(stream))),
+ )
+}
+
+pub fn add_server_tls_stream(stream: ServerTlsStream<TcpStream>) -> ResourceId {
+ let mut table = lock_resource_table();
+ table.add(
+ "serverTlsStream",
+ Box::new(CliResource::ServerTlsStream(Box::new(stream))),
+ )
+}
+
+pub fn add_reqwest_body(body: ReqwestDecoder) -> ResourceId {
+ let body = HttpBody::from(body);
+ let mut table = lock_resource_table();
+ table.add("httpBody", Box::new(CliResource::HttpBody(body)))
+}
+
+pub fn add_child_stdin(stdin: tokio_process::ChildStdin) -> ResourceId {
+ let mut table = lock_resource_table();
+ table.add("childStdin", Box::new(CliResource::ChildStdin(stdin)))
+}
+
+pub fn add_child_stdout(stdout: tokio_process::ChildStdout) -> ResourceId {
+ let mut table = lock_resource_table();
+ table.add("childStdout", Box::new(CliResource::ChildStdout(stdout)))
+}
+
+pub fn add_child_stderr(stderr: tokio_process::ChildStderr) -> ResourceId {
+ let mut table = lock_resource_table();
+ table.add("childStderr", Box::new(CliResource::ChildStderr(stderr)))
+}
+
+pub struct CloneFileFuture {
+ pub rid: ResourceId,
+}
+
+impl Future for CloneFileFuture {
+ type Item = tokio::fs::File;
+ type Error = ErrBox;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ let mut table = lock_resource_table();
+ let repr = table
+ .get_mut::<CliResource>(self.rid)
+ .ok_or_else(bad_resource)?;
+ match repr {
+ CliResource::FsFile(ref mut file) => {
+ file.poll_try_clone().map_err(ErrBox::from)
+ }
+ _ => Err(bad_resource()),
+ }
+ }
+}