summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/js/deno_unstable.ts1
-rw-r--r--cli/js/lib.deno.unstable.d.ts24
-rw-r--r--cli/js/ops/fs/sync.ts10
-rw-r--r--cli/ops/fs.rs45
-rw-r--r--cli/tests/unit/sync_test.ts38
-rw-r--r--cli/tests/unit/unit_tests.ts1
6 files changed, 119 insertions, 0 deletions
diff --git a/cli/js/deno_unstable.ts b/cli/js/deno_unstable.ts
index d8624c675..967eafdcd 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 { fsyncSync, fsync } from "./ops/fs/sync.ts";
export { symlinkSync, symlink } from "./ops/fs/symlink.ts";
export { loadavg, osRelease, hostname } from "./ops/os.ts";
export { openPlugin } from "./ops/plugins.ts";
diff --git a/cli/js/lib.deno.unstable.d.ts b/cli/js/lib.deno.unstable.d.ts
index 3339bfbac..daecf6604 100644
--- a/cli/js/lib.deno.unstable.d.ts
+++ b/cli/js/lib.deno.unstable.d.ts
@@ -1118,4 +1118,28 @@ declare namespace Deno {
* ```
*/
export function ftruncate(rid: number, len?: number): Promise<void>;
+
+ /** **UNSTABLE**: New API, yet to be vetted.
+ * Synchronously flushes any pending data and metadata operations of the given file stream to disk.
+ * ```ts
+ * const file = Deno.openSync("my_file.txt", { read: true, write: true, create: true });
+ * Deno.writeSync(file.rid, new TextEncoder().encode("Hello World"));
+ * Deno.ftruncateSync(file.rid, 1);
+ * Deno.fsyncSync(file.rid);
+ * console.log(new TextDecoder().decode(Deno.readFileSync("my_file.txt"))); // H
+ * ```
+ */
+ export function fsyncSync(rid: number): void;
+
+ /** **UNSTABLE**: New API, yet to be vetted.
+ * Flushes any pending data and metadata operations of the given file stream to disk.
+ * ```ts
+ * const file = await Deno.open("my_file.txt", { read: true, write: true, create: true });
+ * await Deno.write(file.rid, new TextEncoder().encode("Hello World"));
+ * await Deno.ftruncate(file.rid, 1);
+ * await Deno.fsync(file.rid);
+ * console.log(new TextDecoder().decode(await Deno.readFile("my_file.txt"))); // H
+ * ```
+ */
+ export function fsync(rid: number): Promise<void>;
}
diff --git a/cli/js/ops/fs/sync.ts b/cli/js/ops/fs/sync.ts
new file mode 100644
index 000000000..5d5de7242
--- /dev/null
+++ b/cli/js/ops/fs/sync.ts
@@ -0,0 +1,10 @@
+// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
+import { sendSync, sendAsync } from "../dispatch_json.ts";
+
+export function fsyncSync(rid: number): void {
+ sendSync("op_fsync", { rid });
+}
+
+export async function fsync(rid: number): Promise<void> {
+ await sendAsync("op_fsync", { rid });
+}
diff --git a/cli/ops/fs.rs b/cli/ops/fs.rs
index 9ca4b31ae..9417c112d 100644
--- a/cli/ops/fs.rs
+++ b/cli/ops/fs.rs
@@ -22,6 +22,7 @@ use rand::{thread_rng, Rng};
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_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));
@@ -206,6 +207,50 @@ fn op_seek(
}
#[derive(Deserialize)]
+#[serde(rename_all = "camelCase")]
+struct FsyncArgs {
+ promise_id: Option<u64>,
+ rid: i32,
+}
+
+fn op_fsync(
+ isolate_state: &mut CoreIsolateState,
+ state: &State,
+ args: Value,
+ _zero_copy: &mut [ZeroCopyBuf],
+) -> Result<JsonOp, OpError> {
+ state.check_unstable("Deno.fsync");
+ let args: FsyncArgs = 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();
+ std_file_resource(&mut resource_table, rid, |r| match r {
+ Ok(std_file) => std_file.sync_all().map_err(OpError::from),
+ Err(_) => Err(OpError::type_error(
+ "cannot sync this type of resource".to_string(),
+ )),
+ })?;
+ Ok(JsonOp::Sync(json!({})))
+ } else {
+ let fut = async move {
+ let mut resource_table = resource_table.borrow_mut();
+ std_file_resource(&mut resource_table, rid, |r| match r {
+ Ok(std_file) => std_file.sync_all().map_err(OpError::from),
+ Err(_) => Err(OpError::type_error(
+ "cannot sync this type of resource".to_string(),
+ )),
+ })?;
+ Ok(json!({}))
+ };
+ Ok(JsonOp::Async(fut.boxed_local()))
+ }
+}
+
+#[derive(Deserialize)]
struct UmaskArgs {
mask: Option<u32>,
}
diff --git a/cli/tests/unit/sync_test.ts b/cli/tests/unit/sync_test.ts
new file mode 100644
index 000000000..7a489e951
--- /dev/null
+++ b/cli/tests/unit/sync_test.ts
@@ -0,0 +1,38 @@
+// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
+import { unitTest, assertEquals } from "./test_util.ts";
+
+unitTest(
+ { perms: { read: true, write: true } },
+ function fsyncSyncSuccess(): void {
+ const filename = Deno.makeTempDirSync() + "/test_fsyncSync.txt";
+ const file = Deno.openSync(filename, {
+ read: true,
+ write: true,
+ create: true,
+ });
+ const size = 64;
+ Deno.ftruncateSync(file.rid, size);
+ Deno.fsyncSync(file.rid);
+ assertEquals(Deno.statSync(filename).size, size);
+ Deno.close(file.rid);
+ Deno.removeSync(filename);
+ }
+);
+
+unitTest(
+ { perms: { read: true, write: true } },
+ async function fsyncSuccess(): Promise<void> {
+ const filename = (await Deno.makeTempDir()) + "/test_fsync.txt";
+ const file = await Deno.open(filename, {
+ read: true,
+ write: true,
+ create: true,
+ });
+ const size = 64;
+ await Deno.ftruncate(file.rid, size);
+ await Deno.fsync(file.rid);
+ assertEquals((await Deno.stat(filename)).size, size);
+ Deno.close(file.rid);
+ await Deno.remove(filename);
+ }
+);
diff --git a/cli/tests/unit/unit_tests.ts b/cli/tests/unit/unit_tests.ts
index b16141bdc..1701170d1 100644
--- a/cli/tests/unit/unit_tests.ts
+++ b/cli/tests/unit/unit_tests.ts
@@ -59,6 +59,7 @@ import "./streams_piping_test.ts";
import "./streams_transform_test.ts";
import "./streams_writable_test.ts";
import "./symlink_test.ts";
+import "./sync_test.ts";
import "./text_encoding_test.ts";
import "./testing_test.ts";
import "./timers_test.ts";