diff options
Diffstat (limited to 'ext/node')
-rw-r--r-- | ext/node/lib.rs | 3 | ||||
-rw-r--r-- | ext/node/ops/fs.rs | 51 | ||||
-rw-r--r-- | ext/node/polyfills/_fs/_fs_futimes.ts | 16 | ||||
-rw-r--r-- | ext/node/polyfills/_fs/_fs_lutimes.ts | 85 | ||||
-rw-r--r-- | ext/node/polyfills/_fs/_fs_utimes.ts | 13 | ||||
-rw-r--r-- | ext/node/polyfills/fs.ts | 16 | ||||
-rw-r--r-- | ext/node/polyfills/internal/fs/utils.mjs | 4 |
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); } |