summaryrefslogtreecommitdiff
path: root/ext/node
diff options
context:
space:
mode:
Diffstat (limited to 'ext/node')
-rw-r--r--ext/node/lib.rs3
-rw-r--r--ext/node/ops/fs.rs51
-rw-r--r--ext/node/polyfills/_fs/_fs_futimes.ts16
-rw-r--r--ext/node/polyfills/_fs/_fs_lutimes.ts85
-rw-r--r--ext/node/polyfills/_fs/_fs_utimes.ts13
-rw-r--r--ext/node/polyfills/fs.ts16
-rw-r--r--ext/node/polyfills/internal/fs/utils.mjs4
7 files changed, 180 insertions, 8 deletions
diff --git a/ext/node/lib.rs b/ext/node/lib.rs
index ff979a8ba..01c464df1 100644
--- a/ext/node/lib.rs
+++ b/ext/node/lib.rs
@@ -315,6 +315,8 @@ deno_core::extension!(deno_node,
ops::fs::op_node_fs_exists_sync<P>,
ops::fs::op_node_cp_sync<P>,
ops::fs::op_node_cp<P>,
+ ops::fs::op_node_lutimes_sync<P>,
+ ops::fs::op_node_lutimes<P>,
ops::fs::op_node_statfs<P>,
ops::winerror::op_node_sys_to_uv_error,
ops::v8::op_v8_cached_data_version_tag,
@@ -426,6 +428,7 @@ deno_core::extension!(deno_node,
"_fs/_fs_futimes.ts",
"_fs/_fs_link.ts",
"_fs/_fs_lstat.ts",
+ "_fs/_fs_lutimes.ts",
"_fs/_fs_mkdir.ts",
"_fs/_fs_mkdtemp.ts",
"_fs/_fs_open.ts",
diff --git a/ext/node/ops/fs.rs b/ext/node/ops/fs.rs
index cfc760656..304a6c253 100644
--- a/ext/node/ops/fs.rs
+++ b/ext/node/ops/fs.rs
@@ -222,3 +222,54 @@ where
Err(anyhow!("Unsupported platform."))
}
}
+
+#[op2(fast)]
+pub fn op_node_lutimes_sync<P>(
+ state: &mut OpState,
+ #[string] path: &str,
+ #[number] atime_secs: i64,
+ #[smi] atime_nanos: u32,
+ #[number] mtime_secs: i64,
+ #[smi] mtime_nanos: u32,
+) -> Result<(), AnyError>
+where
+ P: NodePermissions + 'static,
+{
+ let path = Path::new(path);
+
+ state
+ .borrow_mut::<P>()
+ .check_write_with_api_name(path, Some("node:fs.lutimes"))?;
+
+ let fs = state.borrow::<FileSystemRc>();
+ fs.lutime_sync(path, atime_secs, atime_nanos, mtime_secs, mtime_nanos)?;
+ Ok(())
+}
+
+#[op2(async)]
+pub async fn op_node_lutimes<P>(
+ state: Rc<RefCell<OpState>>,
+ #[string] path: String,
+ #[number] atime_secs: i64,
+ #[smi] atime_nanos: u32,
+ #[number] mtime_secs: i64,
+ #[smi] mtime_nanos: u32,
+) -> Result<(), AnyError>
+where
+ P: NodePermissions + 'static,
+{
+ let path = PathBuf::from(path);
+
+ let fs = {
+ let mut state = state.borrow_mut();
+ state
+ .borrow_mut::<P>()
+ .check_write_with_api_name(&path, Some("node:fs.lutimesSync"))?;
+ state.borrow::<FileSystemRc>().clone()
+ };
+
+ fs.lutime_async(path, atime_secs, atime_nanos, mtime_secs, mtime_nanos)
+ .await?;
+
+ Ok(())
+}
diff --git a/ext/node/polyfills/_fs/_fs_futimes.ts b/ext/node/polyfills/_fs/_fs_futimes.ts
index cc4e35b0b..98cd1066c 100644
--- a/ext/node/polyfills/_fs/_fs_futimes.ts
+++ b/ext/node/polyfills/_fs/_fs_futimes.ts
@@ -5,6 +5,9 @@
import type { CallbackWithError } from "ext:deno_node/_fs/_fs_common.ts";
import { FsFile } from "ext:deno_fs/30_fs.js";
+import { validateInteger } from "ext:deno_node/internal/validators.mjs";
+import { ERR_INVALID_ARG_TYPE } from "ext:deno_node/internal/errors.ts";
+import { toUnixTimestamp } from "ext:deno_node/internal/fs/utils.mjs";
function getValidTime(
time: number | string | Date,
@@ -23,7 +26,7 @@ function getValidTime(
);
}
- return time;
+ return toUnixTimestamp(time);
}
export function futimes(
@@ -35,6 +38,11 @@ export function futimes(
if (!callback) {
throw new Deno.errors.InvalidData("No callback function supplied");
}
+ if (typeof fd !== "number") {
+ throw new ERR_INVALID_ARG_TYPE("fd", "number", fd);
+ }
+
+ validateInteger(fd, "fd", 0, 2147483647);
atime = getValidTime(atime, "atime");
mtime = getValidTime(mtime, "mtime");
@@ -51,6 +59,12 @@ export function futimesSync(
atime: number | string | Date,
mtime: number | string | Date,
) {
+ if (typeof fd !== "number") {
+ throw new ERR_INVALID_ARG_TYPE("fd", "number", fd);
+ }
+
+ validateInteger(fd, "fd", 0, 2147483647);
+
atime = getValidTime(atime, "atime");
mtime = getValidTime(mtime, "mtime");
diff --git a/ext/node/polyfills/_fs/_fs_lutimes.ts b/ext/node/polyfills/_fs/_fs_lutimes.ts
new file mode 100644
index 000000000..2475c5714
--- /dev/null
+++ b/ext/node/polyfills/_fs/_fs_lutimes.ts
@@ -0,0 +1,85 @@
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+
+// deno-lint-ignore-file prefer-primordials
+
+import type { CallbackWithError } from "ext:deno_node/_fs/_fs_common.ts";
+import { type Buffer } from "node:buffer";
+import { primordials } from "ext:core/mod.js";
+import { op_node_lutimes, op_node_lutimes_sync } from "ext:core/ops";
+import { promisify } from "ext:deno_node/internal/util.mjs";
+import {
+ getValidatedPath,
+ toUnixTimestamp,
+} from "ext:deno_node/internal/fs/utils.mjs";
+
+const { MathTrunc } = primordials;
+
+type TimeLike = number | string | Date;
+type PathLike = string | Buffer | URL;
+
+function getValidUnixTime(
+ value: TimeLike,
+ name: string,
+): [number, number] {
+ if (typeof value === "string") {
+ value = Number(value);
+ }
+
+ if (
+ typeof value === "number" &&
+ (Number.isNaN(value) || !Number.isFinite(value))
+ ) {
+ throw new Deno.errors.InvalidData(
+ `invalid ${name}, must not be infinity or NaN`,
+ );
+ }
+
+ const unixSeconds = toUnixTimestamp(value);
+
+ const seconds = MathTrunc(unixSeconds);
+ const nanoseconds = MathTrunc((unixSeconds * 1e3) - (seconds * 1e3)) * 1e6;
+
+ return [
+ seconds,
+ nanoseconds,
+ ];
+}
+
+export function lutimes(
+ path: PathLike,
+ atime: TimeLike,
+ mtime: TimeLike,
+ callback: CallbackWithError,
+): void {
+ if (!callback) {
+ throw new Error("No callback function supplied");
+ }
+ const [atimeSecs, atimeNanos] = getValidUnixTime(atime, "atime");
+ const [mtimeSecs, mtimeNanos] = getValidUnixTime(mtime, "mtime");
+
+ path = getValidatedPath(path).toString();
+
+ op_node_lutimes(path, atimeSecs, atimeNanos, mtimeSecs, mtimeNanos).then(
+ () => callback(null),
+ callback,
+ );
+}
+
+export function lutimesSync(
+ path: PathLike,
+ atime: TimeLike,
+ mtime: TimeLike,
+): void {
+ const { 0: atimeSecs, 1: atimeNanos } = getValidUnixTime(atime, "atime");
+ const { 0: mtimeSecs, 1: mtimeNanos } = getValidUnixTime(mtime, "mtime");
+
+ path = getValidatedPath(path).toString();
+
+ op_node_lutimes_sync(path, atimeSecs, atimeNanos, mtimeSecs, mtimeNanos);
+}
+
+export const lutimesPromise = promisify(lutimes) as (
+ path: PathLike,
+ atime: TimeLike,
+ mtime: TimeLike,
+) => Promise<void>;
diff --git a/ext/node/polyfills/_fs/_fs_utimes.ts b/ext/node/polyfills/_fs/_fs_utimes.ts
index 1d0e5c1ff..3fff4a462 100644
--- a/ext/node/polyfills/_fs/_fs_utimes.ts
+++ b/ext/node/polyfills/_fs/_fs_utimes.ts
@@ -4,13 +4,16 @@
// deno-lint-ignore-file prefer-primordials
import type { CallbackWithError } from "ext:deno_node/_fs/_fs_common.ts";
-import { pathFromURL } from "ext:deno_web/00_infra.js";
import { promisify } from "ext:deno_node/internal/util.mjs";
+import {
+ getValidatedPath,
+ toUnixTimestamp,
+} from "ext:deno_node/internal/fs/utils.mjs";
function getValidTime(
time: number | string | Date,
name: string,
-): number | Date {
+): number {
if (typeof time === "string") {
time = Number(time);
}
@@ -24,7 +27,7 @@ function getValidTime(
);
}
- return time;
+ return toUnixTimestamp(time);
}
export function utimes(
@@ -33,7 +36,7 @@ export function utimes(
mtime: number | string | Date,
callback: CallbackWithError,
) {
- path = path instanceof URL ? pathFromURL(path) : path;
+ path = getValidatedPath(path).toString();
if (!callback) {
throw new Deno.errors.InvalidData("No callback function supplied");
@@ -56,7 +59,7 @@ export function utimesSync(
atime: number | string | Date,
mtime: number | string | Date,
) {
- path = path instanceof URL ? pathFromURL(path) : path;
+ path = getValidatedPath(path).toString();
atime = getValidTime(atime, "atime");
mtime = getValidTime(mtime, "mtime");
diff --git a/ext/node/polyfills/fs.ts b/ext/node/polyfills/fs.ts
index f788f72b5..6f0c53e4d 100644
--- a/ext/node/polyfills/fs.ts
+++ b/ext/node/polyfills/fs.ts
@@ -29,6 +29,11 @@ import { ftruncate, ftruncateSync } from "ext:deno_node/_fs/_fs_ftruncate.ts";
import { futimes, futimesSync } from "ext:deno_node/_fs/_fs_futimes.ts";
import { link, linkPromise, linkSync } from "ext:deno_node/_fs/_fs_link.ts";
import { lstat, lstatPromise, lstatSync } from "ext:deno_node/_fs/_fs_lstat.ts";
+import {
+ lutimes,
+ lutimesPromise,
+ lutimesSync,
+} from "ext:deno_node/_fs/_fs_lutimes.ts";
import { mkdir, mkdirPromise, mkdirSync } from "ext:deno_node/_fs/_fs_mkdir.ts";
import {
mkdtemp,
@@ -123,6 +128,7 @@ import {
ReadStream,
WriteStream,
} from "ext:deno_node/internal/fs/streams.mjs";
+import { toUnixTimestamp as _toUnixTimestamp } from "ext:deno_node/internal/fs/utils.mjs";
const {
F_OK,
@@ -170,7 +176,7 @@ const promises = {
// lchown: promisify(lchown),
chown: chownPromise,
utimes: utimesPromise,
- // lutimes = promisify(lutimes),
+ lutimes: lutimesPromise,
realpath: realpathPromise,
mkdtemp: mkdtempPromise,
writeFile: writeFilePromise,
@@ -216,6 +222,8 @@ export default {
linkSync,
lstat,
lstatSync,
+ lutimes,
+ lutimesSync,
mkdir,
mkdirSync,
mkdtemp,
@@ -284,9 +292,13 @@ export default {
WriteStream,
writeSync,
X_OK,
+ // For tests
+ _toUnixTimestamp,
};
export {
+ // For tests
+ _toUnixTimestamp,
access,
accessSync,
appendFile,
@@ -323,6 +335,8 @@ export {
linkSync,
lstat,
lstatSync,
+ lutimes,
+ lutimesSync,
mkdir,
mkdirSync,
mkdtemp,
diff --git a/ext/node/polyfills/internal/fs/utils.mjs b/ext/node/polyfills/internal/fs/utils.mjs
index ec379ed99..21c5892ce 100644
--- a/ext/node/polyfills/internal/fs/utils.mjs
+++ b/ext/node/polyfills/internal/fs/utils.mjs
@@ -5,6 +5,8 @@
"use strict";
+import { primordials } from "ext:core/mod.js";
+const { DatePrototypeGetTime } = primordials;
import { Buffer } from "node:buffer";
import {
ERR_FS_EISDIR,
@@ -698,7 +700,7 @@ export function toUnixTimestamp(time, name = "time") {
}
if (isDate(time)) {
// Convert to 123.456 UNIX timestamp
- return Date.getTime(time) / 1000;
+ return DatePrototypeGetTime(time) / 1000;
}
throw new ERR_INVALID_ARG_TYPE(name, ["Date", "Time in seconds"], time);
}