mirror of
https://github.com/denoland/deno.git
synced 2025-03-04 01:44:26 -05:00
Add resources op (#1119)
This commit is contained in:
parent
8b39d2c99e
commit
946acbc559
9 changed files with 167 additions and 0 deletions
1
BUILD.gn
1
BUILD.gn
|
@ -102,6 +102,7 @@ ts_sources = [
|
||||||
"js/read_link.ts",
|
"js/read_link.ts",
|
||||||
"js/remove.ts",
|
"js/remove.ts",
|
||||||
"js/rename.ts",
|
"js/rename.ts",
|
||||||
|
"js/resources.ts",
|
||||||
"js/stat.ts",
|
"js/stat.ts",
|
||||||
"js/symlink.ts",
|
"js/symlink.ts",
|
||||||
"js/text_encoding.ts",
|
"js/text_encoding.ts",
|
||||||
|
|
|
@ -38,6 +38,7 @@ export { truncateSync, truncate } from "./truncate";
|
||||||
export { FileInfo } from "./file_info";
|
export { FileInfo } from "./file_info";
|
||||||
export { connect, dial, listen, Listener, Conn } from "./net";
|
export { connect, dial, listen, Listener, Conn } from "./net";
|
||||||
export { metrics } from "./metrics";
|
export { metrics } from "./metrics";
|
||||||
|
export { resources } from "./resources";
|
||||||
export const args: string[] = [];
|
export const args: string[] = [];
|
||||||
|
|
||||||
// Provide the compiler API in an obfuscated way
|
// Provide the compiler API in an obfuscated way
|
||||||
|
|
25
js/resources.ts
Normal file
25
js/resources.ts
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
// Copyright 2018 the Deno authors. All rights reserved. MIT license.
|
||||||
|
import * as msg from "gen/msg_generated";
|
||||||
|
import * as flatbuffers from "./flatbuffers";
|
||||||
|
import { assert } from "./util";
|
||||||
|
import * as dispatch from "./dispatch";
|
||||||
|
|
||||||
|
export function resources(): { [key: number]: string } {
|
||||||
|
const builder = flatbuffers.createBuilder();
|
||||||
|
msg.Resources.startResources(builder);
|
||||||
|
const inner = msg.Resource.endResource(builder);
|
||||||
|
const baseRes = dispatch.sendSync(builder, msg.Any.Resources, inner);
|
||||||
|
assert(baseRes !== null);
|
||||||
|
assert(msg.Any.ResourcesRes === baseRes!.innerType());
|
||||||
|
const res = new msg.ResourcesRes();
|
||||||
|
assert(baseRes!.inner(res) !== null);
|
||||||
|
|
||||||
|
const resources: { [key: number]: string } = {};
|
||||||
|
|
||||||
|
for (let i = 0; i < res.resourcesLength(); i++) {
|
||||||
|
const item = res.resources(i)!;
|
||||||
|
resources[item.rid()!] = item.repr()!;
|
||||||
|
}
|
||||||
|
|
||||||
|
return resources;
|
||||||
|
}
|
43
js/resources_test.ts
Normal file
43
js/resources_test.ts
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
// Copyright 2018 the Deno authors. All rights reserved. MIT license.
|
||||||
|
import { test, testPerm, assert, assertEqual } from "./test_util.ts";
|
||||||
|
import * as deno from "deno";
|
||||||
|
|
||||||
|
test(function resourcesStdio() {
|
||||||
|
const res = deno.resources();
|
||||||
|
|
||||||
|
assertEqual(res[0], "stdin");
|
||||||
|
assertEqual(res[1], "stdout");
|
||||||
|
assertEqual(res[2], "stderr");
|
||||||
|
});
|
||||||
|
|
||||||
|
testPerm({ net: true }, async function resourcesNet() {
|
||||||
|
const addr = "127.0.0.1:4501";
|
||||||
|
const listener = deno.listen("tcp", addr);
|
||||||
|
|
||||||
|
const dialerConn = await deno.dial("tcp", addr);
|
||||||
|
const listenerConn = await listener.accept();
|
||||||
|
|
||||||
|
const res = deno.resources();
|
||||||
|
assertEqual(Object.values(res).filter(r => r === "tcpListener").length, 1);
|
||||||
|
assertEqual(Object.values(res).filter(r => r === "tcpStream").length, 2);
|
||||||
|
|
||||||
|
listenerConn.close();
|
||||||
|
dialerConn.close();
|
||||||
|
listener.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
test(async function resourcesFile() {
|
||||||
|
const resourcesBefore = deno.resources();
|
||||||
|
await deno.open("tests/hello.txt");
|
||||||
|
const resourcesAfter = deno.resources();
|
||||||
|
|
||||||
|
// check that exactly one new resource (file) was added
|
||||||
|
assertEqual(
|
||||||
|
Object.keys(resourcesAfter).length,
|
||||||
|
Object.keys(resourcesBefore).length + 1
|
||||||
|
);
|
||||||
|
const newRid = Object.keys(resourcesAfter).find(rid => {
|
||||||
|
return !resourcesBefore.hasOwnProperty(rid);
|
||||||
|
});
|
||||||
|
assertEqual(resourcesAfter[newRid], "fsFile");
|
||||||
|
});
|
|
@ -22,6 +22,7 @@ import "./read_dir_test.ts";
|
||||||
import "./read_file_test.ts";
|
import "./read_file_test.ts";
|
||||||
import "./read_link_test.ts";
|
import "./read_link_test.ts";
|
||||||
import "./rename_test.ts";
|
import "./rename_test.ts";
|
||||||
|
import "./resources_test.ts";
|
||||||
import "./stat_test.ts";
|
import "./stat_test.ts";
|
||||||
import "./symlink_test.ts";
|
import "./symlink_test.ts";
|
||||||
import "./text_encoding_test.ts";
|
import "./text_encoding_test.ts";
|
||||||
|
|
13
src/msg.fbs
13
src/msg.fbs
|
@ -24,6 +24,8 @@ union Any {
|
||||||
Rename,
|
Rename,
|
||||||
Readlink,
|
Readlink,
|
||||||
ReadlinkRes,
|
ReadlinkRes,
|
||||||
|
Resources,
|
||||||
|
ResourcesRes,
|
||||||
Symlink,
|
Symlink,
|
||||||
Stat,
|
Stat,
|
||||||
StatRes,
|
StatRes,
|
||||||
|
@ -270,6 +272,17 @@ table ReadlinkRes {
|
||||||
path: string;
|
path: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table Resources {}
|
||||||
|
|
||||||
|
table Resource {
|
||||||
|
rid: int;
|
||||||
|
repr: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
table ResourcesRes {
|
||||||
|
resources: [Resource];
|
||||||
|
}
|
||||||
|
|
||||||
table Symlink {
|
table Symlink {
|
||||||
oldname: string;
|
oldname: string;
|
||||||
newname: string;
|
newname: string;
|
||||||
|
|
48
src/ops.rs
48
src/ops.rs
|
@ -19,6 +19,7 @@ use futures::Poll;
|
||||||
use hyper;
|
use hyper;
|
||||||
use hyper::rt::{Future, Stream};
|
use hyper::rt::{Future, Stream};
|
||||||
use remove_dir_all::remove_dir_all;
|
use remove_dir_all::remove_dir_all;
|
||||||
|
use resources::table_entries;
|
||||||
use std;
|
use std;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::net::{Shutdown, SocketAddr};
|
use std::net::{Shutdown, SocketAddr};
|
||||||
|
@ -94,6 +95,7 @@ pub fn dispatch(
|
||||||
msg::Any::Read => op_read,
|
msg::Any::Read => op_read,
|
||||||
msg::Any::Remove => op_remove,
|
msg::Any::Remove => op_remove,
|
||||||
msg::Any::Rename => op_rename,
|
msg::Any::Rename => op_rename,
|
||||||
|
msg::Any::Resources => op_resources,
|
||||||
msg::Any::SetEnv => op_set_env,
|
msg::Any::SetEnv => op_set_env,
|
||||||
msg::Any::Shutdown => op_shutdown,
|
msg::Any::Shutdown => op_shutdown,
|
||||||
msg::Any::Start => op_start,
|
msg::Any::Start => op_start,
|
||||||
|
@ -1288,3 +1290,49 @@ fn op_metrics(
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn op_resources(
|
||||||
|
_state: Arc<IsolateState>,
|
||||||
|
base: &msg::Base,
|
||||||
|
data: &'static mut [u8],
|
||||||
|
) -> Box<Op> {
|
||||||
|
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.clone(),
|
||||||
|
repr: Some(repr),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}).collect();
|
||||||
|
|
||||||
|
let resources = builder.create_vector(&res);
|
||||||
|
let inner = msg::ResourcesRes::create(
|
||||||
|
builder,
|
||||||
|
&msg::ResourcesResArgs {
|
||||||
|
resources: Some(resources),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
ok_future(serialize_response(
|
||||||
|
cmd_id,
|
||||||
|
builder,
|
||||||
|
msg::BaseArgs {
|
||||||
|
inner: Some(inner.as_union_value()),
|
||||||
|
inner_type: msg::Any::ResourcesRes,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
|
@ -58,6 +58,40 @@ enum Repr {
|
||||||
TcpStream(tokio::net::TcpStream),
|
TcpStream(tokio::net::TcpStream),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn table_entries() -> Vec<(i32, String)> {
|
||||||
|
let table = RESOURCE_TABLE.lock().unwrap();
|
||||||
|
|
||||||
|
let tuples = table
|
||||||
|
.iter()
|
||||||
|
.map(|(key, value)| (key.clone(), inspect_repr(&value)))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
tuples
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_table_entries() {
|
||||||
|
let mut entries = table_entries();
|
||||||
|
entries.sort();
|
||||||
|
assert_eq!(entries.len(), 3);
|
||||||
|
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",
|
||||||
|
};
|
||||||
|
|
||||||
|
String::from(h_repr)
|
||||||
|
}
|
||||||
|
|
||||||
// Abstract async file interface.
|
// Abstract async file interface.
|
||||||
// Ideally in unix, if Resource represents an OS rid, it will be the same.
|
// Ideally in unix, if Resource represents an OS rid, it will be the same.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
1
tests/hello.txt
Normal file
1
tests/hello.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Hello world!
|
Loading…
Add table
Reference in a new issue