summaryrefslogtreecommitdiff
path: root/ext/node/polyfills/_fs/_fs_stat.ts
diff options
context:
space:
mode:
authorBartek IwaƄczuk <biwanczuk@gmail.com>2023-02-14 17:38:45 +0100
committerGitHub <noreply@github.com>2023-02-14 17:38:45 +0100
commitd47147fb6ad229b1c039aff9d0959b6e281f4df5 (patch)
tree6e9e790f2b9bc71b5f0c9c7e64b95cae31579d58 /ext/node/polyfills/_fs/_fs_stat.ts
parent1d00bbe47e2ca14e2d2151518e02b2324461a065 (diff)
feat(ext/node): embed std/node into the snapshot (#17724)
This commit moves "deno_std/node" in "ext/node" crate. The code is transpiled and snapshotted during the build process. During the first pass a minimal amount of work was done to create the snapshot, a lot of code in "ext/node" depends on presence of "Deno" global. This code will be gradually fixed in the follow up PRs to migrate it to import relevant APIs from "internal:" modules. Currently the code from snapshot is not used in any way, and all Node/npm compatibility still uses code from "https://deno.land/std/node" (or from the location specified by "DENO_NODE_COMPAT_URL"). This will also be handled in a follow up PRs. --------- Co-authored-by: crowlkats <crowlkats@toaxl.com> Co-authored-by: Divy Srivastava <dj.srivastava23@gmail.com> Co-authored-by: Yoshiya Hinosawa <stibium121@gmail.com>
Diffstat (limited to 'ext/node/polyfills/_fs/_fs_stat.ts')
-rw-r--r--ext/node/polyfills/_fs/_fs_stat.ts314
1 files changed, 314 insertions, 0 deletions
diff --git a/ext/node/polyfills/_fs/_fs_stat.ts b/ext/node/polyfills/_fs/_fs_stat.ts
new file mode 100644
index 000000000..3a006084d
--- /dev/null
+++ b/ext/node/polyfills/_fs/_fs_stat.ts
@@ -0,0 +1,314 @@
+// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
+import { denoErrorToNodeError } from "internal:deno_node/polyfills/internal/errors.ts";
+import { promisify } from "internal:deno_node/polyfills/internal/util.mjs";
+
+export type statOptions = {
+ bigint: boolean;
+ throwIfNoEntry?: boolean;
+};
+
+export type Stats = {
+ /** ID of the device containing the file.
+ *
+ * _Linux/Mac OS only._ */
+ dev: number | null;
+ /** Inode number.
+ *
+ * _Linux/Mac OS only._ */
+ ino: number | null;
+ /** **UNSTABLE**: Match behavior with Go on Windows for `mode`.
+ *
+ * The underlying raw `st_mode` bits that contain the standard Unix
+ * permissions for this file/directory. */
+ mode: number | null;
+ /** Number of hard links pointing to this file.
+ *
+ * _Linux/Mac OS only._ */
+ nlink: number | null;
+ /** User ID of the owner of this file.
+ *
+ * _Linux/Mac OS only._ */
+ uid: number | null;
+ /** Group ID of the owner of this file.
+ *
+ * _Linux/Mac OS only._ */
+ gid: number | null;
+ /** Device ID of this file.
+ *
+ * _Linux/Mac OS only._ */
+ rdev: number | null;
+ /** The size of the file, in bytes. */
+ size: number;
+ /** Blocksize for filesystem I/O.
+ *
+ * _Linux/Mac OS only._ */
+ blksize: number | null;
+ /** Number of blocks allocated to the file, in 512-byte units.
+ *
+ * _Linux/Mac OS only._ */
+ blocks: number | null;
+ /** The last modification time of the file. This corresponds to the `mtime`
+ * field from `stat` on Linux/Mac OS and `ftLastWriteTime` on Windows. This
+ * may not be available on all platforms. */
+ mtime: Date | null;
+ /** The last access time of the file. This corresponds to the `atime`
+ * field from `stat` on Unix and `ftLastAccessTime` on Windows. This may not
+ * be available on all platforms. */
+ atime: Date | null;
+ /** The creation time of the file. This corresponds to the `birthtime`
+ * field from `stat` on Mac/BSD and `ftCreationTime` on Windows. This may
+ * not be available on all platforms. */
+ birthtime: Date | null;
+ /** change time */
+ ctime: Date | null;
+ /** atime in milliseconds */
+ atimeMs: number | null;
+ /** atime in milliseconds */
+ mtimeMs: number | null;
+ /** atime in milliseconds */
+ ctimeMs: number | null;
+ /** atime in milliseconds */
+ birthtimeMs: number | null;
+ isBlockDevice: () => boolean;
+ isCharacterDevice: () => boolean;
+ isDirectory: () => boolean;
+ isFIFO: () => boolean;
+ isFile: () => boolean;
+ isSocket: () => boolean;
+ isSymbolicLink: () => boolean;
+};
+
+export type BigIntStats = {
+ /** ID of the device containing the file.
+ *
+ * _Linux/Mac OS only._ */
+ dev: bigint | null;
+ /** Inode number.
+ *
+ * _Linux/Mac OS only._ */
+ ino: bigint | null;
+ /** **UNSTABLE**: Match behavior with Go on Windows for `mode`.
+ *
+ * The underlying raw `st_mode` bits that contain the standard Unix
+ * permissions for this file/directory. */
+ mode: bigint | null;
+ /** Number of hard links pointing to this file.
+ *
+ * _Linux/Mac OS only._ */
+ nlink: bigint | null;
+ /** User ID of the owner of this file.
+ *
+ * _Linux/Mac OS only._ */
+ uid: bigint | null;
+ /** Group ID of the owner of this file.
+ *
+ * _Linux/Mac OS only._ */
+ gid: bigint | null;
+ /** Device ID of this file.
+ *
+ * _Linux/Mac OS only._ */
+ rdev: bigint | null;
+ /** The size of the file, in bytes. */
+ size: bigint;
+ /** Blocksize for filesystem I/O.
+ *
+ * _Linux/Mac OS only._ */
+ blksize: bigint | null;
+ /** Number of blocks allocated to the file, in 512-byte units.
+ *
+ * _Linux/Mac OS only._ */
+ blocks: bigint | null;
+ /** The last modification time of the file. This corresponds to the `mtime`
+ * field from `stat` on Linux/Mac OS and `ftLastWriteTime` on Windows. This
+ * may not be available on all platforms. */
+ mtime: Date | null;
+ /** The last access time of the file. This corresponds to the `atime`
+ * field from `stat` on Unix and `ftLastAccessTime` on Windows. This may not
+ * be available on all platforms. */
+ atime: Date | null;
+ /** The creation time of the file. This corresponds to the `birthtime`
+ * field from `stat` on Mac/BSD and `ftCreationTime` on Windows. This may
+ * not be available on all platforms. */
+ birthtime: Date | null;
+ /** change time */
+ ctime: Date | null;
+ /** atime in milliseconds */
+ atimeMs: bigint | null;
+ /** atime in milliseconds */
+ mtimeMs: bigint | null;
+ /** atime in milliseconds */
+ ctimeMs: bigint | null;
+ /** atime in nanoseconds */
+ birthtimeMs: bigint | null;
+ /** atime in nanoseconds */
+ atimeNs: bigint | null;
+ /** atime in nanoseconds */
+ mtimeNs: bigint | null;
+ /** atime in nanoseconds */
+ ctimeNs: bigint | null;
+ /** atime in nanoseconds */
+ birthtimeNs: bigint | null;
+ isBlockDevice: () => boolean;
+ isCharacterDevice: () => boolean;
+ isDirectory: () => boolean;
+ isFIFO: () => boolean;
+ isFile: () => boolean;
+ isSocket: () => boolean;
+ isSymbolicLink: () => boolean;
+};
+
+export function convertFileInfoToStats(origin: Deno.FileInfo): Stats {
+ return {
+ dev: origin.dev,
+ ino: origin.ino,
+ mode: origin.mode,
+ nlink: origin.nlink,
+ uid: origin.uid,
+ gid: origin.gid,
+ rdev: origin.rdev,
+ size: origin.size,
+ blksize: origin.blksize,
+ blocks: origin.blocks,
+ mtime: origin.mtime,
+ atime: origin.atime,
+ birthtime: origin.birthtime,
+ mtimeMs: origin.mtime?.getTime() || null,
+ atimeMs: origin.atime?.getTime() || null,
+ birthtimeMs: origin.birthtime?.getTime() || null,
+ isFile: () => origin.isFile,
+ isDirectory: () => origin.isDirectory,
+ isSymbolicLink: () => origin.isSymlink,
+ // not sure about those
+ isBlockDevice: () => false,
+ isFIFO: () => false,
+ isCharacterDevice: () => false,
+ isSocket: () => false,
+ ctime: origin.mtime,
+ ctimeMs: origin.mtime?.getTime() || null,
+ };
+}
+
+function toBigInt(number?: number | null) {
+ if (number === null || number === undefined) return null;
+ return BigInt(number);
+}
+
+export function convertFileInfoToBigIntStats(
+ origin: Deno.FileInfo,
+): BigIntStats {
+ return {
+ dev: toBigInt(origin.dev),
+ ino: toBigInt(origin.ino),
+ mode: toBigInt(origin.mode),
+ nlink: toBigInt(origin.nlink),
+ uid: toBigInt(origin.uid),
+ gid: toBigInt(origin.gid),
+ rdev: toBigInt(origin.rdev),
+ size: toBigInt(origin.size) || 0n,
+ blksize: toBigInt(origin.blksize),
+ blocks: toBigInt(origin.blocks),
+ mtime: origin.mtime,
+ atime: origin.atime,
+ birthtime: origin.birthtime,
+ mtimeMs: origin.mtime ? BigInt(origin.mtime.getTime()) : null,
+ atimeMs: origin.atime ? BigInt(origin.atime.getTime()) : null,
+ birthtimeMs: origin.birthtime ? BigInt(origin.birthtime.getTime()) : null,
+ mtimeNs: origin.mtime ? BigInt(origin.mtime.getTime()) * 1000000n : null,
+ atimeNs: origin.atime ? BigInt(origin.atime.getTime()) * 1000000n : null,
+ birthtimeNs: origin.birthtime
+ ? BigInt(origin.birthtime.getTime()) * 1000000n
+ : null,
+ isFile: () => origin.isFile,
+ isDirectory: () => origin.isDirectory,
+ isSymbolicLink: () => origin.isSymlink,
+ // not sure about those
+ isBlockDevice: () => false,
+ isFIFO: () => false,
+ isCharacterDevice: () => false,
+ isSocket: () => false,
+ ctime: origin.mtime,
+ ctimeMs: origin.mtime ? BigInt(origin.mtime.getTime()) : null,
+ ctimeNs: origin.mtime ? BigInt(origin.mtime.getTime()) * 1000000n : null,
+ };
+}
+
+// shortcut for Convert File Info to Stats or BigIntStats
+export function CFISBIS(fileInfo: Deno.FileInfo, bigInt: boolean) {
+ if (bigInt) return convertFileInfoToBigIntStats(fileInfo);
+ return convertFileInfoToStats(fileInfo);
+}
+
+export type statCallbackBigInt = (err: Error | null, stat: BigIntStats) => void;
+
+export type statCallback = (err: Error | null, stat: Stats) => void;
+
+export function stat(path: string | URL, callback: statCallback): void;
+export function stat(
+ path: string | URL,
+ options: { bigint: false },
+ callback: statCallback,
+): void;
+export function stat(
+ path: string | URL,
+ options: { bigint: true },
+ callback: statCallbackBigInt,
+): void;
+export function stat(
+ path: string | URL,
+ optionsOrCallback: statCallback | statCallbackBigInt | statOptions,
+ maybeCallback?: statCallback | statCallbackBigInt,
+) {
+ const callback =
+ (typeof optionsOrCallback === "function"
+ ? optionsOrCallback
+ : maybeCallback) as (
+ ...args: [Error] | [null, BigIntStats | Stats]
+ ) => void;
+ const options = typeof optionsOrCallback === "object"
+ ? optionsOrCallback
+ : { bigint: false };
+
+ if (!callback) throw new Error("No callback function supplied");
+
+ Deno.stat(path).then(
+ (stat) => callback(null, CFISBIS(stat, options.bigint)),
+ (err) => callback(denoErrorToNodeError(err, { syscall: "stat" })),
+ );
+}
+
+export const statPromise = promisify(stat) as (
+ & ((path: string | URL) => Promise<Stats>)
+ & ((path: string | URL, options: { bigint: false }) => Promise<Stats>)
+ & ((path: string | URL, options: { bigint: true }) => Promise<BigIntStats>)
+);
+
+export function statSync(path: string | URL): Stats;
+export function statSync(
+ path: string | URL,
+ options: { bigint: false; throwIfNoEntry?: boolean },
+): Stats;
+export function statSync(
+ path: string | URL,
+ options: { bigint: true; throwIfNoEntry?: boolean },
+): BigIntStats;
+export function statSync(
+ path: string | URL,
+ options: statOptions = { bigint: false, throwIfNoEntry: true },
+): Stats | BigIntStats | undefined {
+ try {
+ const origin = Deno.statSync(path);
+ return CFISBIS(origin, options.bigint);
+ } catch (err) {
+ if (
+ options?.throwIfNoEntry === false &&
+ err instanceof Deno.errors.NotFound
+ ) {
+ return;
+ }
+ if (err instanceof Error) {
+ throw denoErrorToNodeError(err, { syscall: "stat" });
+ } else {
+ throw err;
+ }
+ }
+}