summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/js/deno_unstable.ts1
-rw-r--r--cli/js/lib.deno.unstable.d.ts22
-rw-r--r--cli/js/ops/fs/stat.ts8
-rw-r--r--cli/ops/fs.rs46
-rw-r--r--cli/tests/unit/stat_test.ts30
5 files changed, 107 insertions, 0 deletions
diff --git a/cli/js/deno_unstable.ts b/cli/js/deno_unstable.ts
index 967eafdcd..2327b554d 100644
--- a/cli/js/deno_unstable.ts
+++ b/cli/js/deno_unstable.ts
@@ -4,6 +4,7 @@
export { umask } from "./ops/fs/umask.ts";
export { linkSync, link } from "./ops/fs/link.ts";
+export { fstatSync, fstat } from "./ops/fs/stat.ts";
export { fsyncSync, fsync } from "./ops/fs/sync.ts";
export { symlinkSync, symlink } from "./ops/fs/symlink.ts";
export { loadavg, osRelease, hostname } from "./ops/os.ts";
diff --git a/cli/js/lib.deno.unstable.d.ts b/cli/js/lib.deno.unstable.d.ts
index daecf6604..cc7dea987 100644
--- a/cli/js/lib.deno.unstable.d.ts
+++ b/cli/js/lib.deno.unstable.d.ts
@@ -1142,4 +1142,26 @@ declare namespace Deno {
* ```
*/
export function fsync(rid: number): Promise<void>;
+
+ /** **UNSTABLE**: New API, yet to be vetted.
+ * Synchronously returns a `Deno.FileInfo` for the given file stream.
+ *
+ * ```ts
+ * const file = Deno.openSync("file.txt", { read: true });
+ * const fileInfo = Deno.fstatSync(file.rid);
+ * assert(fileInfo.isFile);
+ * ```
+ */
+ export function fstatSync(rid: number): FileInfo;
+
+ /** **UNSTABLE**: New API, yet to be vetted.
+ * Returns a `Deno.FileInfo` for the given file stream.
+ *
+ * ```ts
+ * const file = await Deno.open("file.txt", { read: true });
+ * const fileInfo = await Deno.fstat(file.rid);
+ * assert(fileInfo.isFile);
+ * ```
+ */
+ export function fstat(rid: number): Promise<FileInfo>;
}
diff --git a/cli/js/ops/fs/stat.ts b/cli/js/ops/fs/stat.ts
index 93d31fc3f..402adeafc 100644
--- a/cli/js/ops/fs/stat.ts
+++ b/cli/js/ops/fs/stat.ts
@@ -66,6 +66,14 @@ export function parseFileInfo(response: StatResponse): FileInfo {
};
}
+export function fstatSync(rid: number): FileInfo {
+ return parseFileInfo(sendSync("op_fstat", { rid }));
+}
+
+export async function fstat(rid: number): Promise<FileInfo> {
+ return parseFileInfo(await sendAsync("op_fstat", { rid }));
+}
+
export async function lstat(path: string | URL): Promise<FileInfo> {
path = pathFromURL(path);
const res = (await sendAsync("op_stat", {
diff --git a/cli/ops/fs.rs b/cli/ops/fs.rs
index 9417c112d..7c8100605 100644
--- a/cli/ops/fs.rs
+++ b/cli/ops/fs.rs
@@ -23,6 +23,7 @@ pub fn init(i: &mut CoreIsolate, s: &State) {
i.register_op("op_open", s.stateful_json_op2(op_open));
i.register_op("op_seek", s.stateful_json_op2(op_seek));
i.register_op("op_fsync", s.stateful_json_op2(op_fsync));
+ i.register_op("op_fstat", s.stateful_json_op2(op_fstat));
i.register_op("op_umask", s.stateful_json_op(op_umask));
i.register_op("op_chdir", s.stateful_json_op(op_chdir));
i.register_op("op_mkdir", s.stateful_json_op(op_mkdir));
@@ -251,6 +252,51 @@ fn op_fsync(
}
#[derive(Deserialize)]
+#[serde(rename_all = "camelCase")]
+struct FstatArgs {
+ promise_id: Option<u64>,
+ rid: i32,
+}
+
+fn op_fstat(
+ isolate_state: &mut CoreIsolateState,
+ state: &State,
+ args: Value,
+ _zero_copy: &mut [ZeroCopyBuf],
+) -> Result<JsonOp, OpError> {
+ state.check_unstable("Deno.fstat");
+ let args: FstatArgs = serde_json::from_value(args)?;
+ let rid = args.rid as u32;
+
+ let resource_table = isolate_state.resource_table.clone();
+ let is_sync = args.promise_id.is_none();
+
+ if is_sync {
+ let mut resource_table = resource_table.borrow_mut();
+ let metadata = std_file_resource(&mut resource_table, rid, |r| match r {
+ Ok(std_file) => std_file.metadata().map_err(OpError::from),
+ Err(_) => Err(OpError::type_error(
+ "cannot stat this type of resource".to_string(),
+ )),
+ })?;
+ Ok(JsonOp::Sync(get_stat_json(metadata).unwrap()))
+ } else {
+ let fut = async move {
+ let mut resource_table = resource_table.borrow_mut();
+ let metadata =
+ std_file_resource(&mut resource_table, rid, |r| match r {
+ Ok(std_file) => std_file.metadata().map_err(OpError::from),
+ Err(_) => Err(OpError::type_error(
+ "cannot stat this type of resource".to_string(),
+ )),
+ })?;
+ Ok(get_stat_json(metadata).unwrap())
+ };
+ Ok(JsonOp::Async(fut.boxed_local()))
+ }
+}
+
+#[derive(Deserialize)]
struct UmaskArgs {
mask: Option<u32>,
}
diff --git a/cli/tests/unit/stat_test.ts b/cli/tests/unit/stat_test.ts
index 67598a2d7..b32949286 100644
--- a/cli/tests/unit/stat_test.ts
+++ b/cli/tests/unit/stat_test.ts
@@ -6,6 +6,36 @@ import {
pathToAbsoluteFileUrl,
} from "./test_util.ts";
+unitTest({ perms: { read: true } }, function fstatSyncSuccess(): void {
+ const file = Deno.openSync("README.md");
+ const fileInfo = Deno.fstatSync(file.rid);
+ assert(fileInfo.isFile);
+ assert(!fileInfo.isSymlink);
+ assert(!fileInfo.isDirectory);
+ assert(fileInfo.size);
+ assert(fileInfo.atime);
+ assert(fileInfo.mtime);
+ assert(fileInfo.birthtime);
+
+ Deno.close(file.rid);
+});
+
+unitTest({ perms: { read: true } }, async function fstatSuccess(): Promise<
+ void
+> {
+ const file = await Deno.open("README.md");
+ const fileInfo = await Deno.fstat(file.rid);
+ assert(fileInfo.isFile);
+ assert(!fileInfo.isSymlink);
+ assert(!fileInfo.isDirectory);
+ assert(fileInfo.size);
+ assert(fileInfo.atime);
+ assert(fileInfo.mtime);
+ assert(fileInfo.birthtime);
+
+ Deno.close(file.rid);
+});
+
unitTest(
{ perms: { read: true, write: true } },
function statSyncSuccess(): void {