diff options
Diffstat (limited to 'std/node/_fs')
55 files changed, 0 insertions, 4481 deletions
diff --git a/std/node/_fs/_fs_access.ts b/std/node/_fs/_fs_access.ts deleted file mode 100644 index 3211e1640..000000000 --- a/std/node/_fs/_fs_access.ts +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import type { CallbackWithError } from "./_fs_common.ts"; -import { notImplemented } from "../_utils.ts"; - -/** Revist once https://github.com/denoland/deno/issues/4017 lands */ - -// TODO(bartlomieju) 'path' can also be a Buffer. Neither of these polyfills -//is available yet. See https://github.com/denoland/deno/issues/3403 -export function access( - _path: string | URL, - _modeOrCallback: number | ((...args: unknown[]) => void), - _callback?: CallbackWithError, -): void { - notImplemented("Not yet available"); -} - -// TODO(bartlomieju) 'path' can also be a Buffer. Neither of these polyfills -// is available yet. See https://github.com/denoland/deno/issues/3403 -// eslint-disable-next-line @typescript-eslint/no-unused-vars -export function accessSync(path: string | URL, mode?: number): void { - notImplemented("Not yet available"); -} diff --git a/std/node/_fs/_fs_appendFile.ts b/std/node/_fs/_fs_appendFile.ts deleted file mode 100644 index ee01b9cc8..000000000 --- a/std/node/_fs/_fs_appendFile.ts +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import { - CallbackWithError, - getOpenOptions, - isFileOptions, - WriteFileOptions, -} from "./_fs_common.ts"; -import { Encodings, notImplemented } from "../_utils.ts"; -import { fromFileUrl } from "../path.ts"; - -/** - * TODO: Also accept 'data' parameter as a Node polyfill Buffer type once these - * are implemented. See https://github.com/denoland/deno/issues/3403 - */ -export function appendFile( - pathOrRid: string | number | URL, - data: string | Uint8Array, - optionsOrCallback: Encodings | WriteFileOptions | CallbackWithError, - callback?: CallbackWithError, -): void { - pathOrRid = pathOrRid instanceof URL ? fromFileUrl(pathOrRid) : pathOrRid; - const callbackFn: CallbackWithError | undefined = - optionsOrCallback instanceof Function ? optionsOrCallback : callback; - const options: Encodings | WriteFileOptions | undefined = - optionsOrCallback instanceof Function ? undefined : optionsOrCallback; - if (!callbackFn) { - throw new Error("No callback function supplied"); - } - - validateEncoding(options); - let rid = -1; - const buffer: Uint8Array = data instanceof Uint8Array - ? data - : new TextEncoder().encode(data); - new Promise((resolve, reject) => { - if (typeof pathOrRid === "number") { - rid = pathOrRid; - Deno.write(rid, buffer).then(resolve, reject); - } else { - const mode: number | undefined = isFileOptions(options) - ? options.mode - : undefined; - const flag: string | undefined = isFileOptions(options) - ? options.flag - : undefined; - - if (mode) { - // TODO(bartlomieju) rework once https://github.com/denoland/deno/issues/4017 completes - notImplemented("Deno does not yet support setting mode on create"); - } - Deno.open(pathOrRid as string, getOpenOptions(flag)) - .then(({ rid: openedFileRid }) => { - rid = openedFileRid; - return Deno.write(openedFileRid, buffer); - }) - .then(resolve, reject); - } - }) - .then(() => { - closeRidIfNecessary(typeof pathOrRid === "string", rid); - callbackFn(null); - }, (err) => { - closeRidIfNecessary(typeof pathOrRid === "string", rid); - callbackFn(err); - }); -} - -function closeRidIfNecessary(isPathString: boolean, rid: number): void { - if (isPathString && rid != -1) { - //Only close if a path was supplied and a rid allocated - Deno.close(rid); - } -} - -/** - * TODO: Also accept 'data' parameter as a Node polyfill Buffer type once these - * are implemented. See https://github.com/denoland/deno/issues/3403 - */ -export function appendFileSync( - pathOrRid: string | number | URL, - data: string | Uint8Array, - options?: Encodings | WriteFileOptions, -): void { - let rid = -1; - - validateEncoding(options); - pathOrRid = pathOrRid instanceof URL ? fromFileUrl(pathOrRid) : pathOrRid; - - try { - if (typeof pathOrRid === "number") { - rid = pathOrRid; - } else { - const mode: number | undefined = isFileOptions(options) - ? options.mode - : undefined; - const flag: string | undefined = isFileOptions(options) - ? options.flag - : undefined; - - if (mode) { - // TODO(bartlomieju) rework once https://github.com/denoland/deno/issues/4017 completes - notImplemented("Deno does not yet support setting mode on create"); - } - - const file = Deno.openSync(pathOrRid, getOpenOptions(flag)); - rid = file.rid; - } - - const buffer: Uint8Array = data instanceof Uint8Array - ? data - : new TextEncoder().encode(data); - - Deno.writeSync(rid, buffer); - } finally { - closeRidIfNecessary(typeof pathOrRid === "string", rid); - } -} - -function validateEncoding( - encodingOption: Encodings | WriteFileOptions | undefined, -): void { - if (!encodingOption) return; - - if (typeof encodingOption === "string") { - if (encodingOption !== "utf8") { - throw new Error("Only 'utf8' encoding is currently supported"); - } - } else if (encodingOption.encoding && encodingOption.encoding !== "utf8") { - throw new Error("Only 'utf8' encoding is currently supported"); - } -} diff --git a/std/node/_fs/_fs_appendFile_test.ts b/std/node/_fs/_fs_appendFile_test.ts deleted file mode 100644 index 6a77974fd..000000000 --- a/std/node/_fs/_fs_appendFile_test.ts +++ /dev/null @@ -1,254 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import { assertEquals, assertThrows, fail } from "../../testing/asserts.ts"; -import { appendFile, appendFileSync } from "./_fs_appendFile.ts"; -import { fromFileUrl } from "../path.ts"; -import { assertCallbackErrorUncaught } from "../_utils.ts"; - -const decoder = new TextDecoder("utf-8"); - -Deno.test({ - name: "No callback Fn results in Error", - fn() { - assertThrows( - () => { - appendFile("some/path", "some data", "utf8"); - }, - Error, - "No callback function supplied", - ); - }, -}); - -Deno.test({ - name: "Unsupported encoding results in error()", - fn() { - assertThrows( - () => { - // @ts-expect-error Type '"made-up-encoding"' is not assignable to type - appendFile("some/path", "some data", "made-up-encoding", () => {}); - }, - Error, - "Only 'utf8' encoding is currently supported", - ); - assertThrows( - () => { - appendFile( - "some/path", - "some data", - // @ts-expect-error Type '"made-up-encoding"' is not assignable to type - { encoding: "made-up-encoding" }, - () => {}, - ); - }, - Error, - "Only 'utf8' encoding is currently supported", - ); - assertThrows( - // @ts-expect-error Type '"made-up-encoding"' is not assignable to type - () => appendFileSync("some/path", "some data", "made-up-encoding"), - Error, - "Only 'utf8' encoding is currently supported", - ); - assertThrows( - () => - appendFileSync("some/path", "some data", { - // @ts-expect-error Type '"made-up-encoding"' is not assignable to type - encoding: "made-up-encoding", - }), - Error, - "Only 'utf8' encoding is currently supported", - ); - }, -}); - -Deno.test({ - name: "Async: Data is written to passed in rid", - async fn() { - const tempFile: string = await Deno.makeTempFile(); - const file: Deno.File = await Deno.open(tempFile, { - create: true, - write: true, - read: true, - }); - await new Promise<void>((resolve, reject) => { - appendFile(file.rid, "hello world", (err) => { - if (err) reject(); - else resolve(); - }); - }) - .then(async () => { - const data = await Deno.readFile(tempFile); - assertEquals(decoder.decode(data), "hello world"); - }, () => { - fail("No error expected"); - }) - .finally(async () => { - Deno.close(file.rid); - await Deno.remove(tempFile); - }); - }, -}); - -Deno.test({ - name: "Async: Data is written to passed in file path", - async fn() { - const openResourcesBeforeAppend: Deno.ResourceMap = Deno.resources(); - await new Promise<void>((resolve, reject) => { - appendFile("_fs_appendFile_test_file.txt", "hello world", (err) => { - if (err) reject(err); - else resolve(); - }); - }) - .then(async () => { - assertEquals(Deno.resources(), openResourcesBeforeAppend); - const data = await Deno.readFile("_fs_appendFile_test_file.txt"); - assertEquals(decoder.decode(data), "hello world"); - }, (err) => { - fail("No error was expected: " + err); - }) - .finally(async () => { - await Deno.remove("_fs_appendFile_test_file.txt"); - }); - }, -}); - -Deno.test({ - name: "Async: Data is written to passed in URL", - async fn() { - const openResourcesBeforeAppend: Deno.ResourceMap = Deno.resources(); - const fileURL = new URL("_fs_appendFile_test_file.txt", import.meta.url); - await new Promise<void>((resolve, reject) => { - appendFile(fileURL, "hello world", (err) => { - if (err) reject(err); - else resolve(); - }); - }) - .then(async () => { - assertEquals(Deno.resources(), openResourcesBeforeAppend); - const data = await Deno.readFile(fromFileUrl(fileURL)); - assertEquals(decoder.decode(data), "hello world"); - }, (err) => { - fail("No error was expected: " + err); - }) - .finally(async () => { - await Deno.remove(fromFileUrl(fileURL)); - }); - }, -}); - -Deno.test({ - name: - "Async: Callback is made with error if attempting to append data to an existing file with 'ax' flag", - async fn() { - const openResourcesBeforeAppend: Deno.ResourceMap = Deno.resources(); - const tempFile: string = await Deno.makeTempFile(); - await new Promise<void>((resolve, reject) => { - appendFile(tempFile, "hello world", { flag: "ax" }, (err) => { - if (err) reject(err); - else resolve(); - }); - }) - .then(() => { - fail("Expected error to be thrown"); - }, () => { - assertEquals(Deno.resources(), openResourcesBeforeAppend); - }) - .finally(async () => { - await Deno.remove(tempFile); - }); - }, -}); - -Deno.test({ - name: "Sync: Data is written to passed in rid", - fn() { - const tempFile: string = Deno.makeTempFileSync(); - const file: Deno.File = Deno.openSync(tempFile, { - create: true, - write: true, - read: true, - }); - appendFileSync(file.rid, "hello world"); - Deno.close(file.rid); - const data = Deno.readFileSync(tempFile); - assertEquals(decoder.decode(data), "hello world"); - Deno.removeSync(tempFile); - }, -}); - -Deno.test({ - name: "Sync: Data is written to passed in file path", - fn() { - const openResourcesBeforeAppend: Deno.ResourceMap = Deno.resources(); - appendFileSync("_fs_appendFile_test_file_sync.txt", "hello world"); - assertEquals(Deno.resources(), openResourcesBeforeAppend); - const data = Deno.readFileSync("_fs_appendFile_test_file_sync.txt"); - assertEquals(decoder.decode(data), "hello world"); - Deno.removeSync("_fs_appendFile_test_file_sync.txt"); - }, -}); - -Deno.test({ - name: - "Sync: error thrown if attempting to append data to an existing file with 'ax' flag", - fn() { - const openResourcesBeforeAppend: Deno.ResourceMap = Deno.resources(); - const tempFile: string = Deno.makeTempFileSync(); - assertThrows( - () => appendFileSync(tempFile, "hello world", { flag: "ax" }), - Deno.errors.AlreadyExists, - "", - ); - assertEquals(Deno.resources(), openResourcesBeforeAppend); - Deno.removeSync(tempFile); - }, -}); - -Deno.test({ - name: "Sync: Data is written in Uint8Array to passed in file path", - fn() { - const openResourcesBeforeAppend: Deno.ResourceMap = Deno.resources(); - const testData = new TextEncoder().encode("hello world"); - appendFileSync("_fs_appendFile_test_file_sync.txt", testData); - assertEquals(Deno.resources(), openResourcesBeforeAppend); - const data = Deno.readFileSync("_fs_appendFile_test_file_sync.txt"); - assertEquals(data, testData); - Deno.removeSync("_fs_appendFile_test_file_sync.txt"); - }, -}); - -Deno.test({ - name: "Async: Data is written in Uint8Array to passed in file path", - async fn() { - const openResourcesBeforeAppend: Deno.ResourceMap = Deno.resources(); - const testData = new TextEncoder().encode("hello world"); - await new Promise<void>((resolve, reject) => { - appendFile("_fs_appendFile_test_file.txt", testData, (err) => { - if (err) reject(err); - else resolve(); - }); - }) - .then(async () => { - assertEquals(Deno.resources(), openResourcesBeforeAppend); - const data = await Deno.readFile("_fs_appendFile_test_file.txt"); - assertEquals(data, testData); - }, (err) => { - fail("No error was expected: " + err); - }) - .finally(async () => { - await Deno.remove("_fs_appendFile_test_file.txt"); - }); - }, -}); - -Deno.test("[std/node/fs] appendFile callback isn't called twice if error is thrown", async () => { - const tempFile = await Deno.makeTempFile(); - const importUrl = new URL("./_fs_appendFile.ts", import.meta.url); - await assertCallbackErrorUncaught({ - prelude: `import { appendFile } from ${JSON.stringify(importUrl)}`, - invocation: `appendFile(${JSON.stringify(tempFile)}, "hello world", `, - async cleanup() { - await Deno.remove(tempFile); - }, - }); -}); diff --git a/std/node/_fs/_fs_chmod.ts b/std/node/_fs/_fs_chmod.ts deleted file mode 100644 index bf4031d2c..000000000 --- a/std/node/_fs/_fs_chmod.ts +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import type { CallbackWithError } from "./_fs_common.ts"; -import { fromFileUrl } from "../path.ts"; - -const allowedModes = /^[0-7]{3}/; - -/** - * TODO: Also accept 'path' parameter as a Node polyfill Buffer type once these - * are implemented. See https://github.com/denoland/deno/issues/3403 - */ -export function chmod( - path: string | URL, - mode: string | number, - callback: CallbackWithError, -): void { - path = path instanceof URL ? fromFileUrl(path) : path; - - Deno.chmod(path, getResolvedMode(mode)).then(() => callback(null), callback); -} - -/** - * TODO: Also accept 'path' parameter as a Node polyfill Buffer type once these - * are implemented. See https://github.com/denoland/deno/issues/3403 - */ -export function chmodSync(path: string | URL, mode: string | number): void { - path = path instanceof URL ? fromFileUrl(path) : path; - Deno.chmodSync(path, getResolvedMode(mode)); -} - -function getResolvedMode(mode: string | number): number { - if (typeof mode === "number") { - return mode; - } - - if (typeof mode === "string" && !allowedModes.test(mode)) { - throw new Error("Unrecognized mode: " + mode); - } - - return parseInt(mode, 8); -} diff --git a/std/node/_fs/_fs_chmod_test.ts b/std/node/_fs/_fs_chmod_test.ts deleted file mode 100644 index 4d8647782..000000000 --- a/std/node/_fs/_fs_chmod_test.ts +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import { assert, fail } from "../../testing/asserts.ts"; -import { assertCallbackErrorUncaught } from "../_utils.ts"; -import { chmod, chmodSync } from "./_fs_chmod.ts"; - -Deno.test({ - name: "ASYNC: Permissions are changed (non-Windows)", - ignore: Deno.build.os === "windows", - async fn() { - const tempFile: string = await Deno.makeTempFile(); - const originalFileMode: number | null = (await Deno.lstat(tempFile)).mode; - await new Promise<void>((resolve, reject) => { - chmod(tempFile, 0o777, (err) => { - if (err) reject(err); - else resolve(); - }); - }) - .then(() => { - const newFileMode: number | null = Deno.lstatSync(tempFile).mode; - assert(newFileMode && originalFileMode); - assert(newFileMode === 33279 && newFileMode > originalFileMode); - }, () => { - fail(); - }) - .finally(() => { - Deno.removeSync(tempFile); - }); - }, -}); - -Deno.test({ - name: "SYNC: Permissions are changed (non-Windows)", - ignore: Deno.build.os === "windows", - fn() { - const tempFile: string = Deno.makeTempFileSync(); - const originalFileMode: number | null = Deno.lstatSync(tempFile).mode; - chmodSync(tempFile, "777"); - - const newFileMode: number | null = Deno.lstatSync(tempFile).mode; - assert(newFileMode && originalFileMode); - assert(newFileMode === 33279 && newFileMode > originalFileMode); - Deno.removeSync(tempFile); - }, -}); - -Deno.test({ - name: "[std/node/fs] chmod callback isn't called twice if error is thrown", - ignore: Deno.build.os === "windows", - async fn() { - const tempFile = await Deno.makeTempFile(); - const importUrl = new URL("./_fs_chmod.ts", import.meta.url); - await assertCallbackErrorUncaught({ - prelude: `import { chmod } from ${JSON.stringify(importUrl)}`, - invocation: `chmod(${JSON.stringify(tempFile)}, 0o777, `, - async cleanup() { - await Deno.remove(tempFile); - }, - }); - }, -}); diff --git a/std/node/_fs/_fs_chown.ts b/std/node/_fs/_fs_chown.ts deleted file mode 100644 index f9e7326ce..000000000 --- a/std/node/_fs/_fs_chown.ts +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import type { CallbackWithError } from "./_fs_common.ts"; -import { fromFileUrl } from "../path.ts"; - -/** - * TODO: Also accept 'path' parameter as a Node polyfill Buffer type once these - * are implemented. See https://github.com/denoland/deno/issues/3403 - */ -export function chown( - path: string | URL, - uid: number, - gid: number, - callback: CallbackWithError, -): void { - path = path instanceof URL ? fromFileUrl(path) : path; - - Deno.chown(path, uid, gid).then(() => callback(null), callback); -} - -/** - * TODO: Also accept 'path' parameter as a Node polyfill Buffer type once these - * are implemented. See https://github.com/denoland/deno/issues/3403 - */ -export function chownSync(path: string | URL, uid: number, gid: number): void { - path = path instanceof URL ? fromFileUrl(path) : path; - - Deno.chownSync(path, uid, gid); -} diff --git a/std/node/_fs/_fs_chown_test.ts b/std/node/_fs/_fs_chown_test.ts deleted file mode 100644 index 8d74f657a..000000000 --- a/std/node/_fs/_fs_chown_test.ts +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import { assertEquals, fail } from "../../testing/asserts.ts"; -import { assertCallbackErrorUncaught } from "../_utils.ts"; -import { chown, chownSync } from "./_fs_chown.ts"; - -// chown is difficult to test. Best we can do is set the existing user id/group -// id again -const ignore = Deno.build.os == "windows"; - -Deno.test({ - ignore, - name: "ASYNC: setting existing uid/gid works as expected (non-Windows)", - async fn() { - const tempFile: string = await Deno.makeTempFile(); - const originalUserId: number | null = (await Deno.lstat(tempFile)).uid; - const originalGroupId: number | null = (await Deno.lstat(tempFile)).gid; - await new Promise<void>((resolve, reject) => { - chown(tempFile, originalUserId!, originalGroupId!, (err) => { - if (err) reject(err); - else resolve(); - }); - }) - .then(() => { - const newUserId: number | null = Deno.lstatSync(tempFile).uid; - const newGroupId: number | null = Deno.lstatSync(tempFile).gid; - assertEquals(newUserId, originalUserId); - assertEquals(newGroupId, originalGroupId); - }, () => { - fail(); - }) - .finally(() => { - Deno.removeSync(tempFile); - }); - }, -}); - -Deno.test({ - ignore, - name: "SYNC: setting existing uid/gid works as expected (non-Windows)", - fn() { - const tempFile: string = Deno.makeTempFileSync(); - const originalUserId: number | null = Deno.lstatSync(tempFile).uid; - const originalGroupId: number | null = Deno.lstatSync(tempFile).gid; - chownSync(tempFile, originalUserId!, originalGroupId!); - - const newUserId: number | null = Deno.lstatSync(tempFile).uid; - const newGroupId: number | null = Deno.lstatSync(tempFile).gid; - assertEquals(newUserId, originalUserId); - assertEquals(newGroupId, originalGroupId); - Deno.removeSync(tempFile); - }, -}); - -Deno.test({ - name: "[std/node/fs] chown callback isn't called twice if error is thrown", - ignore: Deno.build.os === "windows", - async fn() { - const tempFile = await Deno.makeTempFile(); - const { uid, gid } = await Deno.lstat(tempFile); - const importUrl = new URL("./_fs_chown.ts", import.meta.url); - await assertCallbackErrorUncaught({ - prelude: `import { chown } from ${JSON.stringify(importUrl)}`, - invocation: `chown(${JSON.stringify(tempFile)}, ${uid}, ${gid}, `, - async cleanup() { - await Deno.remove(tempFile); - }, - }); - }, -}); diff --git a/std/node/_fs/_fs_close.ts b/std/node/_fs/_fs_close.ts deleted file mode 100644 index 721827421..000000000 --- a/std/node/_fs/_fs_close.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import type { CallbackWithError } from "./_fs_common.ts"; - -export function close(fd: number, callback: CallbackWithError): void { - setTimeout(() => { - let error = null; - try { - Deno.close(fd); - } catch (err) { - error = err; - } - callback(error); - }, 0); -} - -export function closeSync(fd: number): void { - Deno.close(fd); -} diff --git a/std/node/_fs/_fs_close_test.ts b/std/node/_fs/_fs_close_test.ts deleted file mode 100644 index df5a93240..000000000 --- a/std/node/_fs/_fs_close_test.ts +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import { assert, assertThrows, fail } from "../../testing/asserts.ts"; -import { assertCallbackErrorUncaught } from "../_utils.ts"; -import { close, closeSync } from "./_fs_close.ts"; - -Deno.test({ - name: "ASYNC: File is closed", - async fn() { - const tempFile: string = await Deno.makeTempFile(); - const file: Deno.File = await Deno.open(tempFile); - - assert(Deno.resources()[file.rid]); - await new Promise<void>((resolve, reject) => { - close(file.rid, (err) => { - if (err !== null) reject(); - else resolve(); - }); - }) - .then(() => { - assert(!Deno.resources()[file.rid]); - }, () => { - fail("No error expected"); - }) - .finally(async () => { - await Deno.remove(tempFile); - }); - }, -}); - -Deno.test({ - name: "ASYNC: Invalid fd", - async fn() { - await new Promise<void>((resolve, reject) => { - close(-1, (err) => { - if (err !== null) return resolve(); - reject(); - }); - }); - }, -}); - -Deno.test({ - name: "close callback should be asynchronous", - async fn() { - const tempFile: string = Deno.makeTempFileSync(); - const file: Deno.File = Deno.openSync(tempFile); - - let foo: string; - const promise = new Promise<void>((resolve) => { - close(file.rid, () => { - assert(foo === "bar"); - resolve(); - }); - foo = "bar"; - }); - - await promise; - Deno.removeSync(tempFile); - }, -}); - -Deno.test({ - name: "SYNC: File is closed", - fn() { - const tempFile: string = Deno.makeTempFileSync(); - const file: Deno.File = Deno.openSync(tempFile); - - assert(Deno.resources()[file.rid]); - closeSync(file.rid); - assert(!Deno.resources()[file.rid]); - Deno.removeSync(tempFile); - }, -}); - -Deno.test({ - name: "SYNC: Invalid fd", - fn() { - assertThrows(() => closeSync(-1)); - }, -}); - -Deno.test("[std/node/fs] close callback isn't called twice if error is thrown", async () => { - const tempFile = await Deno.makeTempFile(); - const importUrl = new URL("./_fs_close.ts", import.meta.url); - await assertCallbackErrorUncaught({ - prelude: ` - import { close } from ${JSON.stringify(importUrl)}; - - const file = await Deno.open(${JSON.stringify(tempFile)}); - `, - invocation: "close(file.rid, ", - async cleanup() { - await Deno.remove(tempFile); - }, - }); -}); diff --git a/std/node/_fs/_fs_common.ts b/std/node/_fs/_fs_common.ts deleted file mode 100644 index c233b2d76..000000000 --- a/std/node/_fs/_fs_common.ts +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import { - BinaryEncodings, - Encodings, - notImplemented, - TextEncodings, -} from "../_utils.ts"; - -export type CallbackWithError = (err: Error | null) => void; - -export interface FileOptions { - encoding?: Encodings; - flag?: string; -} - -export type TextOptionsArgument = - | TextEncodings - | ({ encoding: TextEncodings } & FileOptions); -export type BinaryOptionsArgument = - | BinaryEncodings - | ({ encoding: BinaryEncodings } & FileOptions); -export type FileOptionsArgument = Encodings | FileOptions; - -export interface WriteFileOptions extends FileOptions { - mode?: number; -} - -export function isFileOptions( - fileOptions: string | WriteFileOptions | undefined, -): fileOptions is FileOptions { - if (!fileOptions) return false; - - return ( - (fileOptions as FileOptions).encoding != undefined || - (fileOptions as FileOptions).flag != undefined || - (fileOptions as WriteFileOptions).mode != undefined - ); -} - -export function getEncoding( - optOrCallback?: - | FileOptions - | WriteFileOptions - // deno-lint-ignore no-explicit-any - | ((...args: any[]) => any) - | Encodings - | null, -): Encodings | null { - if (!optOrCallback || typeof optOrCallback === "function") { - return null; - } - - const encoding = typeof optOrCallback === "string" - ? optOrCallback - : optOrCallback.encoding; - if (!encoding) return null; - return encoding; -} - -export function checkEncoding(encoding: Encodings | null): Encodings | null { - if (!encoding) return null; - - encoding = encoding.toLowerCase() as Encodings; - if (["utf8", "hex", "base64"].includes(encoding)) return encoding; - - if (encoding === "utf-8") { - return "utf8"; - } - if (encoding === "binary") { - return "binary"; - // before this was buffer, however buffer is not used in Node - // node -e "require('fs').readFile('../world.txt', 'buffer', console.log)" - } - - const notImplementedEncodings = ["utf16le", "latin1", "ascii", "ucs2"]; - - if (notImplementedEncodings.includes(encoding as string)) { - notImplemented(`"${encoding}" encoding`); - } - - throw new Error(`The value "${encoding}" is invalid for option "encoding"`); -} - -export function getOpenOptions(flag: string | undefined): Deno.OpenOptions { - if (!flag) { - return { create: true, append: true }; - } - - let openOptions: Deno.OpenOptions; - switch (flag) { - case "a": { - // 'a': Open file for appending. The file is created if it does not exist. - openOptions = { create: true, append: true }; - break; - } - case "ax": { - // 'ax': Like 'a' but fails if the path exists. - openOptions = { createNew: true, write: true, append: true }; - break; - } - case "a+": { - // 'a+': Open file for reading and appending. The file is created if it does not exist. - openOptions = { read: true, create: true, append: true }; - break; - } - case "ax+": { - // 'ax+': Like 'a+' but fails if the path exists. - openOptions = { read: true, createNew: true, append: true }; - break; - } - case "r": { - // 'r': Open file for reading. An exception occurs if the file does not exist. - openOptions = { read: true }; - break; - } - case "r+": { - // 'r+': Open file for reading and writing. An exception occurs if the file does not exist. - openOptions = { read: true, write: true }; - break; - } - case "w": { - // 'w': Open file for writing. The file is created (if it does not exist) or truncated (if it exists). - openOptions = { create: true, write: true, truncate: true }; - break; - } - case "wx": { - // 'wx': Like 'w' but fails if the path exists. - openOptions = { createNew: true, write: true }; - break; - } - case "w+": { - // 'w+': Open file for reading and writing. The file is created (if it does not exist) or truncated (if it exists). - openOptions = { create: true, write: true, truncate: true, read: true }; - break; - } - case "wx+": { - // 'wx+': Like 'w+' but fails if the path exists. - openOptions = { createNew: true, write: true, read: true }; - break; - } - case "as": { - // 'as': Open file for appending in synchronous mode. The file is created if it does not exist. - openOptions = { create: true, append: true }; - break; - } - case "as+": { - // 'as+': Open file for reading and appending in synchronous mode. The file is created if it does not exist. - openOptions = { create: true, read: true, append: true }; - break; - } - case "rs+": { - // 'rs+': Open file for reading and writing in synchronous mode. Instructs the operating system to bypass the local file system cache. - openOptions = { create: true, read: true, write: true }; - break; - } - default: { - throw new Error(`Unrecognized file system flag: ${flag}`); - } - } - - return openOptions; -} diff --git a/std/node/_fs/_fs_constants.ts b/std/node/_fs/_fs_constants.ts deleted file mode 100644 index 7f740276b..000000000 --- a/std/node/_fs/_fs_constants.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. - -//File access constants -export const F_OK = 0; -export const R_OK = 4; -export const W_OK = 2; -export const X_OK = 1; - -//File mode constants -export const S_IRUSR = 0o400; //read by owner -export const S_IWUSR = 0o200; //write by owner -export const S_IXUSR = 0o100; //execute/search by owner -export const S_IRGRP = 0o40; //read by group -export const S_IWGRP = 0o20; //write by group -export const S_IXGRP = 0o10; //execute/search by group -export const S_IROTH = 0o4; //read by others -export const S_IWOTH = 0o2; //write by others -export const S_IXOTH = 0o1; //execute/search by others diff --git a/std/node/_fs/_fs_copy.ts b/std/node/_fs/_fs_copy.ts deleted file mode 100644 index 3242b97b3..000000000 --- a/std/node/_fs/_fs_copy.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import type { CallbackWithError } from "./_fs_common.ts"; -import { fromFileUrl } from "../path.ts"; - -export function copyFile( - source: string | URL, - destination: string, - callback: CallbackWithError, -): void { - source = source instanceof URL ? fromFileUrl(source) : source; - - Deno.copyFile(source, destination).then(() => callback(null), callback); -} - -export function copyFileSync(source: string | URL, destination: string): void { - source = source instanceof URL ? fromFileUrl(source) : source; - Deno.copyFileSync(source, destination); -} diff --git a/std/node/_fs/_fs_copy_test.ts b/std/node/_fs/_fs_copy_test.ts deleted file mode 100644 index 4fdf78cb0..000000000 --- a/std/node/_fs/_fs_copy_test.ts +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import * as path from "../../path/mod.ts"; -import { assert } from "../../testing/asserts.ts"; -import { assertCallbackErrorUncaught } from "../_utils.ts"; -import { copyFile, copyFileSync } from "./_fs_copy.ts"; -import { existsSync } from "./_fs_exists.ts"; - -const destFile = "./destination.txt"; - -Deno.test({ - name: "[std/node/fs] copy file", - fn: async () => { - const sourceFile = Deno.makeTempFileSync(); - const err = await new Promise((resolve) => { - copyFile(sourceFile, destFile, (err?: Error | null) => resolve(err)); - }); - assert(!err); - assert(existsSync(destFile)); - Deno.removeSync(sourceFile); - Deno.removeSync(destFile); - }, -}); - -Deno.test({ - name: "[std/node/fs] copy file sync", - fn: () => { - const sourceFile = Deno.makeTempFileSync(); - copyFileSync(sourceFile, destFile); - assert(existsSync(destFile)); - Deno.removeSync(sourceFile); - Deno.removeSync(destFile); - }, -}); - -Deno.test("[std/node/fs] copyFile callback isn't called twice if error is thrown", async () => { - // The correct behaviour is not to catch any errors thrown, - // but that means there'll be an uncaught error and the test will fail. - // So the only way to test this is to spawn a subprocess, and succeed if it has a non-zero exit code. - // (assertThrowsAsync won't work because there's no way to catch the error.) - const tempDir = await Deno.makeTempDir(); - const tempFile1 = path.join(tempDir, "file1.txt"); - const tempFile2 = path.join(tempDir, "file2.txt"); - await Deno.writeTextFile(tempFile1, "hello world"); - const importUrl = new URL("./_fs_copy.ts", import.meta.url); - await assertCallbackErrorUncaught({ - prelude: `import { copyFile } from ${JSON.stringify(importUrl)}`, - invocation: `copyFile(${JSON.stringify(tempFile1)}, - ${JSON.stringify(tempFile2)}, `, - async cleanup() { - await Deno.remove(tempDir, { recursive: true }); - }, - }); -}); diff --git a/std/node/_fs/_fs_dir.ts b/std/node/_fs/_fs_dir.ts deleted file mode 100644 index 4f7beec31..000000000 --- a/std/node/_fs/_fs_dir.ts +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import Dirent from "./_fs_dirent.ts"; -import { assert } from "../../_util/assert.ts"; - -export default class Dir { - private dirPath: string | Uint8Array; - private syncIterator!: Iterator<Deno.DirEntry> | null; - private asyncIterator!: AsyncIterator<Deno.DirEntry> | null; - - constructor(path: string | Uint8Array) { - this.dirPath = path; - } - - get path(): string { - if (this.dirPath instanceof Uint8Array) { - return new TextDecoder().decode(this.dirPath); - } - return this.dirPath; - } - - // deno-lint-ignore no-explicit-any - read(callback?: (...args: any[]) => void): Promise<Dirent | null> { - return new Promise((resolve, reject) => { - if (!this.asyncIterator) { - this.asyncIterator = Deno.readDir(this.path)[Symbol.asyncIterator](); - } - assert(this.asyncIterator); - this.asyncIterator - .next() - .then(({ value }) => { - resolve(value ? value : null); - if (callback) { - callback(null, value ? value : null); - } - }, (err) => { - if (callback) { - callback(err); - } - reject(err); - }); - }); - } - - readSync(): Dirent | null { - if (!this.syncIterator) { - this.syncIterator = Deno.readDirSync(this.path)![Symbol.iterator](); - } - - const file: Deno.DirEntry = this.syncIterator.next().value; - - return file ? new Dirent(file) : null; - } - - /** - * Unlike Node, Deno does not require managing resource ids for reading - * directories, and therefore does not need to close directories when - * finished reading. - */ - // deno-lint-ignore no-explicit-any - close(callback?: (...args: any[]) => void): Promise<void> { - return new Promise((resolve) => { - if (callback) { - callback(null); - } - resolve(); - }); - } - - /** - * Unlike Node, Deno does not require managing resource ids for reading - * directories, and therefore does not need to close directories when - * finished reading - */ - closeSync(): void { - //No op - } - - async *[Symbol.asyncIterator](): AsyncIterableIterator<Dirent> { - try { - while (true) { - const dirent: Dirent | null = await this.read(); - if (dirent === null) { - break; - } - yield dirent; - } - } finally { - await this.close(); - } - } -} diff --git a/std/node/_fs/_fs_dir_test.ts b/std/node/_fs/_fs_dir_test.ts deleted file mode 100644 index f12563fd5..000000000 --- a/std/node/_fs/_fs_dir_test.ts +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import { assert, assertEquals, fail } from "../../testing/asserts.ts"; -import { assertCallbackErrorUncaught } from "../_utils.ts"; -import Dir from "./_fs_dir.ts"; -import type Dirent from "./_fs_dirent.ts"; - -Deno.test({ - name: "Closing current directory with callback is successful", - fn() { - let calledBack = false; - // deno-lint-ignore no-explicit-any - new Dir(".").close((valOrErr: any) => { - assert(!valOrErr); - calledBack = true; - }); - assert(calledBack); - }, -}); - -Deno.test({ - name: "Closing current directory without callback returns void Promise", - async fn() { - await new Dir(".").close(); - }, -}); - -Deno.test({ - name: "Closing current directory synchronously works", - fn() { - new Dir(".").closeSync(); - }, -}); - -Deno.test({ - name: "Path is correctly returned", - fn() { - assertEquals(new Dir("std/node").path, "std/node"); - - const enc: Uint8Array = new TextEncoder().encode("std/node"); - assertEquals(new Dir(enc).path, "std/node"); - }, -}); - -Deno.test({ - name: "read returns null for empty directory", - async fn() { - const testDir: string = Deno.makeTempDirSync(); - try { - const file: Dirent | null = await new Dir(testDir).read(); - assert(file === null); - - let calledBack = false; - const fileFromCallback: Dirent | null = await new Dir( - testDir, - // deno-lint-ignore no-explicit-any - ).read((err: any, res: Dirent) => { - assert(res === null); - assert(err === null); - calledBack = true; - }); - assert(fileFromCallback === null); - assert(calledBack); - - assertEquals(new Dir(testDir).readSync(), null); - } finally { - Deno.removeSync(testDir); - } - }, -}); - -Deno.test({ - name: "Async read returns one file at a time", - async fn() { - const testDir: string = Deno.makeTempDirSync(); - const f1 = Deno.createSync(testDir + "/foo.txt"); - f1.close(); - const f2 = Deno.createSync(testDir + "/bar.txt"); - f2.close(); - - try { - let secondCallback = false; - const dir: Dir = new Dir(testDir); - const firstRead: Dirent | null = await dir.read(); - const secondRead: Dirent | null = await dir.read( - // deno-lint-ignore no-explicit-any - (err: any, secondResult: Dirent) => { - assert( - secondResult.name === "bar.txt" || - secondResult.name === "foo.txt", - ); - secondCallback = true; - }, - ); - const thirdRead: Dirent | null = await dir.read(); - const fourthRead: Dirent | null = await dir.read(); - - if (firstRead?.name === "foo.txt") { - assertEquals(secondRead?.name, "bar.txt"); - } else if (firstRead?.name === "bar.txt") { - assertEquals(secondRead?.name, "foo.txt"); - } else { - fail("File not found during read"); - } - assert(secondCallback); - assert(thirdRead === null); - assert(fourthRead === null); - } finally { - Deno.removeSync(testDir, { recursive: true }); - } - }, -}); - -Deno.test({ - name: "Sync read returns one file at a time", - fn() { - const testDir: string = Deno.makeTempDirSync(); - const f1 = Deno.createSync(testDir + "/foo.txt"); - f1.close(); - const f2 = Deno.createSync(testDir + "/bar.txt"); - f2.close(); - - try { - const dir: Dir = new Dir(testDir); - const firstRead: Dirent | null = dir.readSync(); - const secondRead: Dirent | null = dir.readSync(); - const thirdRead: Dirent | null = dir.readSync(); - const fourthRead: Dirent | null = dir.readSync(); - - if (firstRead?.name === "foo.txt") { - assertEquals(secondRead?.name, "bar.txt"); - } else if (firstRead?.name === "bar.txt") { - assertEquals(secondRead?.name, "foo.txt"); - } else { - fail("File not found during read"); - } - assert(thirdRead === null); - assert(fourthRead === null); - } finally { - Deno.removeSync(testDir, { recursive: true }); - } - }, -}); - -Deno.test({ - name: "Async iteration over existing directory", - async fn() { - const testDir: string = Deno.makeTempDirSync(); - const f1 = Deno.createSync(testDir + "/foo.txt"); - f1.close(); - const f2 = Deno.createSync(testDir + "/bar.txt"); - f2.close(); - - try { - const dir: Dir = new Dir(testDir); - const results: Array<string | null> = []; - - for await (const file of dir[Symbol.asyncIterator]()) { - results.push(file.name); - } - - assert(results.length === 2); - assert(results.includes("foo.txt")); - assert(results.includes("bar.txt")); - } finally { - Deno.removeSync(testDir, { recursive: true }); - } - }, -}); - -Deno.test("[std/node/fs] Dir.close callback isn't called twice if error is thrown", async () => { - const tempDir = await Deno.makeTempDir(); - const importUrl = new URL("./_fs_dir.ts", import.meta.url); - await assertCallbackErrorUncaught({ - prelude: ` - import Dir from ${JSON.stringify(importUrl)}; - - const dir = new Dir(${JSON.stringify(tempDir)}); - `, - invocation: "dir.close(", - async cleanup() { - await Deno.remove(tempDir); - }, - }); -}); - -Deno.test("[std/node/fs] Dir.read callback isn't called twice if error is thrown", async () => { - const tempDir = await Deno.makeTempDir(); - const importUrl = new URL("./_fs_dir.ts", import.meta.url); - await assertCallbackErrorUncaught({ - prelude: ` - import Dir from ${JSON.stringify(importUrl)}; - - const dir = new Dir(${JSON.stringify(tempDir)}); - `, - invocation: "dir.read(", - async cleanup() { - await Deno.remove(tempDir); - }, - }); -}); diff --git a/std/node/_fs/_fs_dirent.ts b/std/node/_fs/_fs_dirent.ts deleted file mode 100644 index b44ebcb02..000000000 --- a/std/node/_fs/_fs_dirent.ts +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import { notImplemented } from "../_utils.ts"; - -export default class Dirent { - constructor(private entry: Deno.DirEntry) {} - - isBlockDevice(): boolean { - notImplemented("Deno does not yet support identification of block devices"); - return false; - } - - isCharacterDevice(): boolean { - notImplemented( - "Deno does not yet support identification of character devices", - ); - return false; - } - - isDirectory(): boolean { - return this.entry.isDirectory; - } - - isFIFO(): boolean { - notImplemented( - "Deno does not yet support identification of FIFO named pipes", - ); - return false; - } - - isFile(): boolean { - return this.entry.isFile; - } - - isSocket(): boolean { - notImplemented("Deno does not yet support identification of sockets"); - return false; - } - - isSymbolicLink(): boolean { - return this.entry.isSymlink; - } - - get name(): string | null { - return this.entry.name; - } -} diff --git a/std/node/_fs/_fs_dirent_test.ts b/std/node/_fs/_fs_dirent_test.ts deleted file mode 100644 index ad599c84c..000000000 --- a/std/node/_fs/_fs_dirent_test.ts +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import { assert, assertEquals, assertThrows } from "../../testing/asserts.ts"; -import Dirent from "./_fs_dirent.ts"; - -class DirEntryMock implements Deno.DirEntry { - name = ""; - isFile = false; - isDirectory = false; - isSymlink = false; -} - -Deno.test({ - name: "Directories are correctly identified", - fn() { - const entry: DirEntryMock = new DirEntryMock(); - entry.isDirectory = true; - entry.isFile = false; - entry.isSymlink = false; - assert(new Dirent(entry).isDirectory()); - assert(!new Dirent(entry).isFile()); - assert(!new Dirent(entry).isSymbolicLink()); - }, -}); - -Deno.test({ - name: "Files are correctly identified", - fn() { - const entry: DirEntryMock = new DirEntryMock(); - entry.isDirectory = false; - entry.isFile = true; - entry.isSymlink = false; - assert(!new Dirent(entry).isDirectory()); - assert(new Dirent(entry).isFile()); - assert(!new Dirent(entry).isSymbolicLink()); - }, -}); - -Deno.test({ - name: "Symlinks are correctly identified", - fn() { - const entry: DirEntryMock = new DirEntryMock(); - entry.isDirectory = false; - entry.isFile = false; - entry.isSymlink = true; - assert(!new Dirent(entry).isDirectory()); - assert(!new Dirent(entry).isFile()); - assert(new Dirent(entry).isSymbolicLink()); - }, -}); - -Deno.test({ - name: "File name is correct", - fn() { - const entry: DirEntryMock = new DirEntryMock(); - entry.name = "my_file"; - assertEquals(new Dirent(entry).name, "my_file"); - }, -}); - -Deno.test({ - name: "Socket and FIFO pipes aren't yet available", - fn() { - const entry: DirEntryMock = new DirEntryMock(); - assertThrows( - () => { - new Dirent(entry).isFIFO(); - }, - Error, - "does not yet support", - ); - assertThrows( - () => { - new Dirent(entry).isSocket(); - }, - Error, - "does not yet support", - ); - }, -}); diff --git a/std/node/_fs/_fs_exists.ts b/std/node/_fs/_fs_exists.ts deleted file mode 100644 index 5cfa26a9d..000000000 --- a/std/node/_fs/_fs_exists.ts +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import { fromFileUrl } from "../path.ts"; - -type ExitsCallback = (exists: boolean) => void; - -/** - * TODO: Also accept 'path' parameter as a Node polyfill Buffer type once these - * are implemented. See https://github.com/denoland/deno/issues/3403 - * Deprecated in node api - */ -export function exists(path: string | URL, callback: ExitsCallback): void { - path = path instanceof URL ? fromFileUrl(path) : path; - Deno.lstat(path).then(() => callback(true), () => callback(false)); -} - -/** - * TODO: Also accept 'path' parameter as a Node polyfill Buffer or URL type once these - * are implemented. See https://github.com/denoland/deno/issues/3403 - */ -export function existsSync(path: string | URL): boolean { - path = path instanceof URL ? fromFileUrl(path) : path; - try { - Deno.lstatSync(path); - return true; - } catch (err) { - if (err instanceof Deno.errors.NotFound) { - return false; - } - throw err; - } -} diff --git a/std/node/_fs/_fs_exists_test.ts b/std/node/_fs/_fs_exists_test.ts deleted file mode 100644 index ab0ae5c15..000000000 --- a/std/node/_fs/_fs_exists_test.ts +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import { - assert, - assertEquals, - assertStringIncludes, -} from "../../testing/asserts.ts"; -import { exists, existsSync } from "./_fs_exists.ts"; - -Deno.test("existsFile", async function () { - const availableFile = await new Promise((resolve) => { - const tmpFilePath = Deno.makeTempFileSync(); - exists(tmpFilePath, (exists: boolean) => { - Deno.removeSync(tmpFilePath); - resolve(exists); - }); - }); - const notAvailableFile = await new Promise((resolve) => { - exists("./notAvailable.txt", (exists: boolean) => resolve(exists)); - }); - assertEquals(availableFile, true); - assertEquals(notAvailableFile, false); -}); - -Deno.test("existsSyncFile", function () { - const tmpFilePath = Deno.makeTempFileSync(); - assertEquals(existsSync(tmpFilePath), true); - Deno.removeSync(tmpFilePath); - assertEquals(existsSync("./notAvailable.txt"), false); -}); - -Deno.test("[std/node/fs] exists callback isn't called twice if error is thrown", async () => { - // This doesn't use `assertCallbackErrorUncaught()` because `exists()` doesn't return a standard node callback, which is what it expects. - const tempFile = await Deno.makeTempFile(); - const importUrl = new URL("./_fs_exists.ts", import.meta.url); - const p = Deno.run({ - cmd: [ - Deno.execPath(), - "eval", - "--no-check", - ` - import { exists } from ${JSON.stringify(importUrl)}; - - exists(${JSON.stringify(tempFile)}, (exists) => { - // If the bug is present and the callback is called again with false (meaning an error occured), - // don't throw another error, so if the subprocess fails we know it had the correct behaviour. - if (exists) throw new Error("success"); - });`, - ], - stderr: "piped", - }); - const status = await p.status(); - const stderr = new TextDecoder().decode(await Deno.readAll(p.stderr)); - p.close(); - p.stderr.close(); - await Deno.remove(tempFile); - assert(!status.success); - assertStringIncludes(stderr, "Error: success"); -}); diff --git a/std/node/_fs/_fs_link.ts b/std/node/_fs/_fs_link.ts deleted file mode 100644 index 14a8189cb..000000000 --- a/std/node/_fs/_fs_link.ts +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import type { CallbackWithError } from "./_fs_common.ts"; -import { fromFileUrl } from "../path.ts"; - -/** - * TODO: Also accept 'path' parameter as a Node polyfill Buffer type once these - * are implemented. See https://github.com/denoland/deno/issues/3403 - */ -export function link( - existingPath: string | URL, - newPath: string | URL, - callback: CallbackWithError, -): void { - existingPath = existingPath instanceof URL - ? fromFileUrl(existingPath) - : existingPath; - newPath = newPath instanceof URL ? fromFileUrl(newPath) : newPath; - - Deno.link(existingPath, newPath).then(() => callback(null), callback); -} - -/** - * TODO: Also accept 'path' parameter as a Node polyfill Buffer type once these - * are implemented. See https://github.com/denoland/deno/issues/3403 - */ -export function linkSync( - existingPath: string | URL, - newPath: string | URL, -): void { - existingPath = existingPath instanceof URL - ? fromFileUrl(existingPath) - : existingPath; - newPath = newPath instanceof URL ? fromFileUrl(newPath) : newPath; - - Deno.linkSync(existingPath, newPath); -} diff --git a/std/node/_fs/_fs_link_test.ts b/std/node/_fs/_fs_link_test.ts deleted file mode 100644 index 9e2aeb8b6..000000000 --- a/std/node/_fs/_fs_link_test.ts +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import * as path from "../../path/mod.ts"; -import { assert, assertEquals, fail } from "../../testing/asserts.ts"; -import { assertCallbackErrorUncaught } from "../_utils.ts"; -import { link, linkSync } from "./_fs_link.ts"; - -Deno.test({ - name: "ASYNC: hard linking files works as expected", - async fn() { - const tempFile: string = await Deno.makeTempFile(); - const linkedFile: string = tempFile + ".link"; - await new Promise<void>((res, rej) => { - link(tempFile, linkedFile, (err) => { - if (err) rej(err); - else res(); - }); - }) - .then(() => { - assertEquals(Deno.statSync(tempFile), Deno.statSync(linkedFile)); - }, () => { - fail("Expected to succeed"); - }) - .finally(() => { - Deno.removeSync(tempFile); - Deno.removeSync(linkedFile); - }); - }, -}); - -Deno.test({ - name: "ASYNC: hard linking files passes error to callback", - async fn() { - let failed = false; - await new Promise<void>((res, rej) => { - link("no-such-file", "no-such-file", (err) => { - if (err) rej(err); - else res(); - }); - }) - .then(() => { - fail("Expected to succeed"); - }, (err) => { - assert(err); - failed = true; - }); - assert(failed); - }, -}); - -Deno.test({ - name: "SYNC: hard linking files works as expected", - fn() { - const tempFile: string = Deno.makeTempFileSync(); - const linkedFile: string = tempFile + ".link"; - linkSync(tempFile, linkedFile); - - assertEquals(Deno.statSync(tempFile), Deno.statSync(linkedFile)); - Deno.removeSync(tempFile); - Deno.removeSync(linkedFile); - }, -}); - -Deno.test("[std/node/fs] link callback isn't called twice if error is thrown", async () => { - const tempDir = await Deno.makeTempDir(); - const tempFile = path.join(tempDir, "file.txt"); - const linkFile = path.join(tempDir, "link.txt"); - await Deno.writeTextFile(tempFile, "hello world"); - const importUrl = new URL("./_fs_link.ts", import.meta.url); - await assertCallbackErrorUncaught({ - prelude: `import { link } from ${JSON.stringify(importUrl)}`, - invocation: `link(${JSON.stringify(tempFile)}, - ${JSON.stringify(linkFile)}, `, - async cleanup() { - await Deno.remove(tempDir, { recursive: true }); - }, - }); -}); diff --git a/std/node/_fs/_fs_lstat.ts b/std/node/_fs/_fs_lstat.ts deleted file mode 100644 index 55624cd5e..000000000 --- a/std/node/_fs/_fs_lstat.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { - BigIntStats, - CFISBIS, - statCallback, - statCallbackBigInt, - statOptions, - Stats, -} from "./_fs_stat.ts"; - -export function lstat(path: string | URL, callback: statCallback): void; -export function lstat( - path: string | URL, - options: { bigint: false }, - callback: statCallback, -): void; -export function lstat( - path: string | URL, - options: { bigint: true }, - callback: statCallbackBigInt, -): void; -export function lstat( - 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.lstat(path).then( - (stat) => callback(null, CFISBIS(stat, options.bigint)), - (err) => callback(err), - ); -} - -export function lstatSync(path: string | URL): Stats; -export function lstatSync( - path: string | URL, - options: { bigint: false }, -): Stats; -export function lstatSync( - path: string | URL, - options: { bigint: true }, -): BigIntStats; -export function lstatSync( - path: string | URL, - options?: statOptions, -): Stats | BigIntStats { - const origin = Deno.lstatSync(path); - return CFISBIS(origin, options?.bigint || false); -} diff --git a/std/node/_fs/_fs_lstat_test.ts b/std/node/_fs/_fs_lstat_test.ts deleted file mode 100644 index b8c562538..000000000 --- a/std/node/_fs/_fs_lstat_test.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { lstat, lstatSync } from "./_fs_lstat.ts"; -import { fail } from "../../testing/asserts.ts"; -import { assertCallbackErrorUncaught } from "../_utils.ts"; -import { assertStats, assertStatsBigInt } from "./_fs_stat_test.ts"; -import type { BigIntStats, Stats } from "./_fs_stat.ts"; - -Deno.test({ - name: "ASYNC: get a file Stats (lstat)", - async fn() { - const file = Deno.makeTempFileSync(); - await new Promise<Stats>((resolve, reject) => { - lstat(file, (err, stat) => { - if (err) reject(err); - resolve(stat); - }); - }) - .then((stat) => { - assertStats(stat, Deno.lstatSync(file)); - }, () => fail()) - .finally(() => { - Deno.removeSync(file); - }); - }, -}); - -Deno.test({ - name: "SYNC: get a file Stats (lstat)", - fn() { - const file = Deno.makeTempFileSync(); - assertStats(lstatSync(file), Deno.lstatSync(file)); - }, -}); - -Deno.test({ - name: "ASYNC: get a file BigInt Stats (lstat)", - async fn() { - const file = Deno.makeTempFileSync(); - await new Promise<BigIntStats>((resolve, reject) => { - lstat(file, { bigint: true }, (err, stat) => { - if (err) reject(err); - resolve(stat); - }); - }) - .then( - (stat) => assertStatsBigInt(stat, Deno.lstatSync(file)), - () => fail(), - ) - .finally(() => Deno.removeSync(file)); - }, -}); - -Deno.test({ - name: "SYNC: BigInt Stats (lstat)", - fn() { - const file = Deno.makeTempFileSync(); - assertStatsBigInt(lstatSync(file, { bigint: true }), Deno.lstatSync(file)); - }, -}); - -Deno.test("[std/node/fs] lstat callback isn't called twice if error is thrown", async () => { - const tempFile = await Deno.makeTempFile(); - const importUrl = new URL("./_fs_lstat.ts", import.meta.url); - await assertCallbackErrorUncaught({ - prelude: `import { lstat } from ${JSON.stringify(importUrl)}`, - invocation: `lstat(${JSON.stringify(tempFile)}, `, - async cleanup() { - await Deno.remove(tempFile); - }, - }); -}); diff --git a/std/node/_fs/_fs_mkdir.ts b/std/node/_fs/_fs_mkdir.ts deleted file mode 100644 index 94cc24a42..000000000 --- a/std/node/_fs/_fs_mkdir.ts +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import type { CallbackWithError } from "./_fs_common.ts"; -import { fromFileUrl } from "../path.ts"; - -/** - * TODO: Also accept 'path' parameter as a Node polyfill Buffer type once these - * are implemented. See https://github.com/denoland/deno/issues/3403 - */ -type MkdirOptions = - | { recursive?: boolean; mode?: number | undefined } - | number - | boolean; - -export function mkdir( - path: string | URL, - options?: MkdirOptions | CallbackWithError, - callback?: CallbackWithError, -): void { - path = path instanceof URL ? fromFileUrl(path) : path; - - let mode = 0o777; - let recursive = false; - - if (typeof options == "function") { - callback = options; - } else if (typeof options === "number") { - mode = options; - } else if (typeof options === "boolean") { - recursive = options; - } else if (options) { - if (options.recursive !== undefined) recursive = options.recursive; - if (options.mode !== undefined) mode = options.mode; - } - if (typeof recursive !== "boolean") { - throw new Deno.errors.InvalidData( - "invalid recursive option , must be a boolean", - ); - } - Deno.mkdir(path, { recursive, mode }) - .then(() => { - if (typeof callback === "function") { - callback(null); - } - }, (err) => { - if (typeof callback === "function") { - callback(err); - } - }); -} - -export function mkdirSync(path: string | URL, options?: MkdirOptions): void { - path = path instanceof URL ? fromFileUrl(path) : path; - let mode = 0o777; - let recursive = false; - - if (typeof options === "number") { - mode = options; - } else if (typeof options === "boolean") { - recursive = options; - } else if (options) { - if (options.recursive !== undefined) recursive = options.recursive; - if (options.mode !== undefined) mode = options.mode; - } - if (typeof recursive !== "boolean") { - throw new Deno.errors.InvalidData( - "invalid recursive option , must be a boolean", - ); - } - - Deno.mkdirSync(path, { recursive, mode }); -} diff --git a/std/node/_fs/_fs_mkdir_test.ts b/std/node/_fs/_fs_mkdir_test.ts deleted file mode 100644 index c13d065fe..000000000 --- a/std/node/_fs/_fs_mkdir_test.ts +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import * as path from "../../path/mod.ts"; -import { assert } from "../../testing/asserts.ts"; -import { assertCallbackErrorUncaught } from "../_utils.ts"; -import { mkdir, mkdirSync } from "./_fs_mkdir.ts"; -import { existsSync } from "./_fs_exists.ts"; - -const tmpDir = "./tmpdir"; - -Deno.test({ - name: "[node/fs] mkdir", - fn: async () => { - const result = await new Promise((resolve) => { - mkdir(tmpDir, (err) => { - err && resolve(false); - resolve(existsSync(tmpDir)); - Deno.removeSync(tmpDir); - }); - }); - assert(result); - }, -}); - -Deno.test({ - name: "[node/fs] mkdirSync", - fn: () => { - mkdirSync(tmpDir); - assert(existsSync(tmpDir)); - Deno.removeSync(tmpDir); - }, -}); - -Deno.test("[std/node/fs] mkdir callback isn't called twice if error is thrown", async () => { - const tempDir = await Deno.makeTempDir(); - const subdir = path.join(tempDir, "subdir"); - const importUrl = new URL("./_fs_mkdir.ts", import.meta.url); - await assertCallbackErrorUncaught({ - prelude: `import { mkdir } from ${JSON.stringify(importUrl)}`, - invocation: `mkdir(${JSON.stringify(subdir)}, `, - async cleanup() { - await Deno.remove(tempDir, { recursive: true }); - }, - }); -}); diff --git a/std/node/_fs/_fs_mkdtemp.ts b/std/node/_fs/_fs_mkdtemp.ts deleted file mode 100644 index 226399aa4..000000000 --- a/std/node/_fs/_fs_mkdtemp.ts +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright Node.js contributors. All rights reserved. MIT License. -import { existsSync } from "./_fs_exists.ts"; -import { mkdir, mkdirSync } from "./_fs_mkdir.ts"; -import { - ERR_INVALID_CALLBACK, - ERR_INVALID_OPT_VALUE_ENCODING, -} from "../_errors.ts"; - -export type mkdtempCallback = ( - err: Error | null, - directory?: string, -) => void; - -// https://nodejs.org/dist/latest-v15.x/docs/api/fs.html#fs_fs_mkdtemp_prefix_options_callback -export function mkdtemp(prefix: string, callback: mkdtempCallback): void; -export function mkdtemp( - prefix: string, - options: { encoding: string } | string, - callback: mkdtempCallback, -): void; -export function mkdtemp( - prefix: string, - optionsOrCallback: { encoding: string } | string | mkdtempCallback, - maybeCallback?: mkdtempCallback, -): void { - const callback: mkdtempCallback | undefined = - typeof optionsOrCallback == "function" ? optionsOrCallback : maybeCallback; - if (!callback) throw new ERR_INVALID_CALLBACK(callback); - - const encoding: string | undefined = parseEncoding(optionsOrCallback); - const path = tempDirPath(prefix); - - mkdir( - path, - { recursive: false, mode: 0o700 }, - (err: Error | null | undefined) => { - if (err) callback(err); - else callback(null, decode(path, encoding)); - }, - ); -} - -// https://nodejs.org/dist/latest-v15.x/docs/api/fs.html#fs_fs_mkdtempsync_prefix_options -export function mkdtempSync( - prefix: string, - options?: { encoding: string } | string, -): string { - const encoding: string | undefined = parseEncoding(options); - const path = tempDirPath(prefix); - - mkdirSync(path, { recursive: false, mode: 0o700 }); - return decode(path, encoding); -} - -function parseEncoding( - optionsOrCallback?: { encoding: string } | string | mkdtempCallback, -): string | undefined { - let encoding: string | undefined; - if (typeof optionsOrCallback == "function") encoding = undefined; - else if (optionsOrCallback instanceof Object) { - encoding = optionsOrCallback?.encoding; - } else encoding = optionsOrCallback; - - if (encoding) { - try { - new TextDecoder(encoding); - } catch (error) { - throw new ERR_INVALID_OPT_VALUE_ENCODING(encoding); - } - } - - return encoding; -} - -function decode(str: string, encoding?: string): string { - if (!encoding) return str; - else { - const decoder = new TextDecoder(encoding); - const encoder = new TextEncoder(); - return decoder.decode(encoder.encode(str)); - } -} - -const CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; -function randomName(): string { - return [...Array(6)].map(() => - CHARS[Math.floor(Math.random() * CHARS.length)] - ).join(""); -} - -function tempDirPath(prefix: string): string { - let path: string; - do { - path = prefix + randomName(); - } while (existsSync(path)); - - return path; -} diff --git a/std/node/_fs/_fs_mkdtemp_test.ts b/std/node/_fs/_fs_mkdtemp_test.ts deleted file mode 100644 index d41c52794..000000000 --- a/std/node/_fs/_fs_mkdtemp_test.ts +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import { - assert, - assertThrows, - assertThrowsAsync, -} from "../../testing/asserts.ts"; -import { mkdtemp, mkdtempSync } from "./_fs_mkdtemp.ts"; -import { existsSync } from "./_fs_exists.ts"; -import { env } from "../process.ts"; -import { isWindows } from "../../_util/os.ts"; -import { promisify } from "../_util/_util_promisify.ts"; - -const prefix = isWindows ? env.TEMP + "\\" : (env.TMPDIR || "/tmp") + "/"; -const doesNotExists = "/does/not/exists/"; -const options = { encoding: "ascii" }; -const badOptions = { encoding: "bogus" }; - -const mkdtempP = promisify(mkdtemp); - -Deno.test({ - name: "[node/fs] mkdtemp", - fn: async () => { - const directory = await mkdtempP(prefix); - assert(existsSync(directory)); - Deno.removeSync(directory); - }, -}); - -Deno.test({ - name: "[node/fs] mkdtemp (does not exists)", - fn: async () => { - await assertThrowsAsync(() => mkdtempP(doesNotExists)); - }, -}); - -Deno.test({ - name: "[node/fs] mkdtemp (with options)", - fn: async () => { - const directory = await mkdtempP(prefix, options); - assert(existsSync(directory)); - Deno.removeSync(directory); - }, -}); - -Deno.test({ - name: "[node/fs] mkdtemp (with bad options)", - fn: async () => { - await assertThrowsAsync(() => mkdtempP(prefix, badOptions)); - }, -}); - -Deno.test({ - name: "[node/fs] mkdtempSync", - fn: () => { - const directory = mkdtempSync(prefix); - const dirExists = existsSync(directory); - Deno.removeSync(directory); - assert(dirExists); - }, -}); - -Deno.test({ - name: "[node/fs] mkdtempSync (does not exists)", - fn: () => { - assertThrows(() => mkdtempSync(doesNotExists)); - }, -}); - -Deno.test({ - name: "[node/fs] mkdtempSync (with options)", - fn: () => { - const directory = mkdtempSync(prefix, options); - const dirExists = existsSync(directory); - Deno.removeSync(directory); - assert(dirExists); - }, -}); - -Deno.test({ - name: "[node/fs] mkdtempSync (with bad options)", - fn: () => { - assertThrows(() => mkdtempSync(prefix, badOptions)); - }, -}); diff --git a/std/node/_fs/_fs_open.ts b/std/node/_fs/_fs_open.ts deleted file mode 100644 index 55ecbdc1e..000000000 --- a/std/node/_fs/_fs_open.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { existsSync } from "../../fs/mod.ts"; -import { fromFileUrl } from "../path.ts"; -import { getOpenOptions } from "./_fs_common.ts"; - -type openFlags = - | "a" - | "ax" - | "a+" - | "ax+" - | "as" - | "as+" - | "r" - | "r+" - | "rs+" - | "w" - | "wx" - | "w+" - | "wx+"; - -type openCallback = (err: Error | null, fd: number) => void; - -function convertFlagAndModeToOptions( - flag?: openFlags, - mode?: number, -): Deno.OpenOptions | undefined { - if (!flag && !mode) return undefined; - if (!flag && mode) return { mode }; - return { ...getOpenOptions(flag), mode }; -} - -export function open(path: string | URL, callback: openCallback): void; -export function open( - path: string | URL, - flags: openFlags, - callback: openCallback, -): void; -export function open( - path: string | URL, - flags: openFlags, - mode: number, - callback: openCallback, -): void; -export function open( - path: string | URL, - flagsOrCallback: openCallback | openFlags, - callbackOrMode?: openCallback | number, - maybeCallback?: openCallback, -) { - const flags = typeof flagsOrCallback === "string" - ? flagsOrCallback - : undefined; - const callback = typeof flagsOrCallback === "function" - ? flagsOrCallback - : typeof callbackOrMode === "function" - ? callbackOrMode - : maybeCallback; - const mode = typeof callbackOrMode === "number" ? callbackOrMode : undefined; - path = path instanceof URL ? fromFileUrl(path) : path; - - if (!callback) throw new Error("No callback function supplied"); - - if (["ax", "ax+", "wx", "wx+"].includes(flags || "") && existsSync(path)) { - const err = new Error(`EEXIST: file already exists, open '${path}'`); - (callback as (err: Error) => void)(err); - } else { - if (flags === "as" || flags === "as+") { - let err: Error | null = null, res: number; - try { - res = openSync(path, flags, mode); - } catch (error) { - err = error; - } - if (err) { - (callback as (err: Error) => void)(err); - } else { - callback(null, res!); - } - return; - } - Deno.open(path, convertFlagAndModeToOptions(flags, mode)).then( - (file) => callback(null, file.rid), - (err) => (callback as (err: Error) => void)(err), - ); - } -} - -export function openSync(path: string | URL): number; -export function openSync(path: string | URL, flags?: openFlags): number; -export function openSync(path: string | URL, mode?: number): number; -export function openSync( - path: string | URL, - flags?: openFlags, - mode?: number, -): number; -export function openSync( - path: string | URL, - flagsOrMode?: openFlags | number, - maybeMode?: number, -) { - const flags = typeof flagsOrMode === "string" ? flagsOrMode : undefined; - const mode = typeof flagsOrMode === "number" ? flagsOrMode : maybeMode; - path = path instanceof URL ? fromFileUrl(path) : path; - - if (["ax", "ax+", "wx", "wx+"].includes(flags || "") && existsSync(path)) { - throw new Error(`EEXIST: file already exists, open '${path}'`); - } - - return Deno.openSync(path, convertFlagAndModeToOptions(flags, mode)).rid; -} diff --git a/std/node/_fs/_fs_open_test.ts b/std/node/_fs/_fs_open_test.ts deleted file mode 100644 index f32a8ce0a..000000000 --- a/std/node/_fs/_fs_open_test.ts +++ /dev/null @@ -1,221 +0,0 @@ -import { - assert, - assertEquals, - assertThrows, - fail, -} from "../../testing/asserts.ts"; -import { assertCallbackErrorUncaught } from "../_utils.ts"; -import { open, openSync } from "./_fs_open.ts"; -import { join, parse } from "../../path/mod.ts"; -import { existsSync } from "../../fs/mod.ts"; -import { closeSync } from "./_fs_close.ts"; - -const tempDir = parse(Deno.makeTempFileSync()).dir; - -Deno.test({ - name: "ASYNC: open file", - async fn() { - const file = Deno.makeTempFileSync(); - let fd1: number; - await new Promise<number>((resolve, reject) => { - open(file, (err, fd) => { - if (err) reject(err); - resolve(fd); - }); - }) - .then((fd) => { - fd1 = fd; - assert(Deno.resources()[fd], `${fd}`); - }, () => fail()) - .finally(() => closeSync(fd1)); - }, -}); - -Deno.test({ - name: "SYNC: open file", - fn() { - const file = Deno.makeTempFileSync(); - const fd = openSync(file); - assert(Deno.resources()[fd]); - closeSync(fd); - }, -}); - -Deno.test({ - name: "open with flag 'a'", - fn() { - const file = join(tempDir, "some_random_file"); - const fd = openSync(file, "a"); - assertEquals(typeof fd, "number"); - assertEquals(existsSync(file), true); - assert(Deno.resources()[fd]); - closeSync(fd); - }, -}); - -Deno.test({ - name: "open with flag 'ax'", - fn() { - const file = Deno.makeTempFileSync(); - assertThrows( - () => { - openSync(file, "ax"); - }, - Error, - `EEXIST: file already exists, open '${file}'`, - ); - Deno.removeSync(file); - }, -}); - -Deno.test({ - name: "open with flag 'a+'", - fn() { - const file = join(tempDir, "some_random_file2"); - const fd = openSync(file, "a+"); - assertEquals(typeof fd, "number"); - assertEquals(existsSync(file), true); - closeSync(fd); - }, -}); - -Deno.test({ - name: "open with flag 'ax+'", - fn() { - const file = Deno.makeTempFileSync(); - assertThrows( - () => { - openSync(file, "ax+"); - }, - Error, - `EEXIST: file already exists, open '${file}'`, - ); - Deno.removeSync(file); - }, -}); - -Deno.test({ - name: "open with flag 'as'", - fn() { - const file = join(tempDir, "some_random_file10"); - const fd = openSync(file, "as"); - assertEquals(existsSync(file), true); - assertEquals(typeof fd, "number"); - closeSync(fd); - }, -}); - -Deno.test({ - name: "open with flag 'as+'", - fn() { - const file = join(tempDir, "some_random_file10"); - const fd = openSync(file, "as+"); - assertEquals(existsSync(file), true); - assertEquals(typeof fd, "number"); - closeSync(fd); - }, -}); - -Deno.test({ - name: "open with flag 'r'", - fn() { - const file = join(tempDir, "some_random_file3"); - assertThrows(() => { - openSync(file, "r"); - }, Error); - }, -}); - -Deno.test({ - name: "open with flag 'r+'", - fn() { - const file = join(tempDir, "some_random_file4"); - assertThrows(() => { - openSync(file, "r+"); - }, Error); - }, -}); - -Deno.test({ - name: "open with flag 'w'", - fn() { - const file = Deno.makeTempFileSync(); - Deno.writeTextFileSync(file, "hi there"); - const fd = openSync(file, "w"); - assertEquals(typeof fd, "number"); - assertEquals(Deno.readTextFileSync(file), ""); - closeSync(fd); - - const file2 = join(tempDir, "some_random_file5"); - const fd2 = openSync(file2, "w"); - assertEquals(typeof fd2, "number"); - assertEquals(existsSync(file2), true); - closeSync(fd2); - }, -}); - -Deno.test({ - name: "open with flag 'wx'", - fn() { - const file = Deno.makeTempFileSync(); - Deno.writeTextFileSync(file, "hi there"); - const fd = openSync(file, "w"); - assertEquals(typeof fd, "number"); - assertEquals(Deno.readTextFileSync(file), ""); - closeSync(fd); - - const file2 = Deno.makeTempFileSync(); - assertThrows( - () => { - openSync(file2, "wx"); - }, - Error, - `EEXIST: file already exists, open '${file2}'`, - ); - }, -}); - -Deno.test({ - name: "open with flag 'w+'", - fn() { - const file = Deno.makeTempFileSync(); - Deno.writeTextFileSync(file, "hi there"); - const fd = openSync(file, "w+"); - assertEquals(typeof fd, "number"); - assertEquals(Deno.readTextFileSync(file), ""); - closeSync(fd); - - const file2 = join(tempDir, "some_random_file6"); - const fd2 = openSync(file2, "w+"); - assertEquals(typeof fd2, "number"); - assertEquals(existsSync(file2), true); - closeSync(fd2); - }, -}); - -Deno.test({ - name: "open with flag 'wx+'", - fn() { - const file = Deno.makeTempFileSync(); - assertThrows( - () => { - openSync(file, "wx+"); - }, - Error, - `EEXIST: file already exists, open '${file}'`, - ); - Deno.removeSync(file); - }, -}); - -Deno.test("[std/node/fs] open callback isn't called twice if error is thrown", async () => { - const tempFile = await Deno.makeTempFile(); - const importUrl = new URL("./_fs_open.ts", import.meta.url); - await assertCallbackErrorUncaught({ - prelude: `import { open } from ${JSON.stringify(importUrl)}`, - invocation: `open(${JSON.stringify(tempFile)}, `, - async cleanup() { - await Deno.remove(tempFile); - }, - }); -}); diff --git a/std/node/_fs/_fs_readFile.ts b/std/node/_fs/_fs_readFile.ts deleted file mode 100644 index 4ad763e25..000000000 --- a/std/node/_fs/_fs_readFile.ts +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import { - BinaryOptionsArgument, - FileOptionsArgument, - getEncoding, - TextOptionsArgument, -} from "./_fs_common.ts"; -import { Buffer } from "../buffer.ts"; -import { fromFileUrl } from "../path.ts"; -import { BinaryEncodings, Encodings, TextEncodings } from "../_utils.ts"; - -function maybeDecode(data: Uint8Array, encoding: TextEncodings): string; -function maybeDecode( - data: Uint8Array, - encoding: BinaryEncodings | null, -): Buffer; -function maybeDecode( - data: Uint8Array, - encoding: Encodings | null, -): string | Buffer { - const buffer = new Buffer(data.buffer, data.byteOffset, data.byteLength); - if (encoding && encoding !== "binary") return buffer.toString(encoding); - return buffer; -} - -type TextCallback = (err: Error | null, data?: string) => void; -type BinaryCallback = (err: Error | null, data?: Buffer) => void; -type GenericCallback = (err: Error | null, data?: string | Buffer) => void; -type Callback = TextCallback | BinaryCallback | GenericCallback; - -export function readFile( - path: string | URL, - options: TextOptionsArgument, - callback: TextCallback, -): void; -export function readFile( - path: string | URL, - options: BinaryOptionsArgument, - callback: BinaryCallback, -): void; -export function readFile( - path: string | URL, - options: null | undefined | FileOptionsArgument, - callback: BinaryCallback, -): void; -export function readFile(path: string | URL, callback: BinaryCallback): void; -export function readFile( - path: string | URL, - optOrCallback?: FileOptionsArgument | Callback | null | undefined, - callback?: Callback, -): void { - path = path instanceof URL ? fromFileUrl(path) : path; - let cb: Callback | undefined; - if (typeof optOrCallback === "function") { - cb = optOrCallback; - } else { - cb = callback; - } - - const encoding = getEncoding(optOrCallback); - - const p = Deno.readFile(path); - - if (cb) { - p.then((data: Uint8Array) => { - if (encoding && encoding !== "binary") { - const text = maybeDecode(data, encoding); - return (cb as TextCallback)(null, text); - } - const buffer = maybeDecode(data, encoding); - (cb as BinaryCallback)(null, buffer); - }, (err) => cb && cb(err)); - } -} - -export function readFileSync( - path: string | URL, - opt: TextOptionsArgument, -): string; -export function readFileSync( - path: string | URL, - opt?: BinaryOptionsArgument, -): Buffer; -export function readFileSync( - path: string | URL, - opt?: FileOptionsArgument, -): string | Buffer { - path = path instanceof URL ? fromFileUrl(path) : path; - const data = Deno.readFileSync(path); - const encoding = getEncoding(opt); - if (encoding && encoding !== "binary") { - const text = maybeDecode(data, encoding); - return text; - } - const buffer = maybeDecode(data, encoding); - return buffer; -} diff --git a/std/node/_fs/_fs_readFile_test.ts b/std/node/_fs/_fs_readFile_test.ts deleted file mode 100644 index 7af32c8a1..000000000 --- a/std/node/_fs/_fs_readFile_test.ts +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import { assertCallbackErrorUncaught } from "../_utils.ts"; -import { readFile, readFileSync } from "./_fs_readFile.ts"; -import * as path from "../../path/mod.ts"; -import { assert, assertEquals } from "../../testing/asserts.ts"; - -const moduleDir = path.dirname(path.fromFileUrl(import.meta.url)); -const testData = path.resolve(moduleDir, "testdata", "hello.txt"); - -Deno.test("readFileSuccess", async function () { - const data = await new Promise((res, rej) => { - readFile(testData, (err, data) => { - if (err) { - rej(err); - } - res(data); - }); - }); - - assert(data instanceof Uint8Array); - assertEquals(new TextDecoder().decode(data as Uint8Array), "hello world"); -}); - -Deno.test("readFileEncodeUtf8Success", async function () { - const data = await new Promise((res, rej) => { - readFile(testData, { encoding: "utf8" }, (err, data) => { - if (err) { - rej(err); - } - res(data); - }); - }); - assertEquals(typeof data, "string"); - assertEquals(data as string, "hello world"); -}); - -Deno.test("readFileEncodeHexSuccess", async function () { - const data = await new Promise((res, rej) => { - readFile(testData, { encoding: "hex" }, (err, data) => { - if (err) { - rej(err); - } - res(data); - }); - }); - - assertEquals(typeof data, "string"); - assertEquals(data as string, "68656c6c6f20776f726c64"); -}); - -Deno.test("readFileEncodeBase64Success", async function () { - const data = await new Promise((res, rej) => { - readFile(testData, { encoding: "base64" }, (err, data) => { - if (err) { - rej(err); - } - res(data); - }); - }); - assertEquals(typeof data, "string"); - assertEquals(data as string, "aGVsbG8gd29ybGQ="); -}); - -Deno.test("readFileEncodingAsString", async function () { - const data = await new Promise((res, rej) => { - readFile(testData, "utf8", (err, data) => { - if (err) { - rej(err); - } - res(data); - }); - }); - - assertEquals(typeof data, "string"); - assertEquals(data as string, "hello world"); -}); - -Deno.test("readFileSyncSuccess", function () { - const data = readFileSync(testData); - assert(data instanceof Uint8Array); - assertEquals(new TextDecoder().decode(data as Uint8Array), "hello world"); -}); - -Deno.test("readFileEncodeUtf8Success", function () { - const data = readFileSync(testData, { encoding: "utf8" }); - assertEquals(typeof data, "string"); - assertEquals(data as string, "hello world"); -}); - -Deno.test("readFileEncodeHexSuccess", function () { - const data = readFileSync(testData, { encoding: "hex" }); - assertEquals(typeof data, "string"); - assertEquals(data as string, "68656c6c6f20776f726c64"); -}); - -Deno.test("readFileEncodeBase64Success", function () { - const data = readFileSync(testData, { encoding: "base64" }); - assertEquals(typeof data, "string"); - assertEquals(data as string, "aGVsbG8gd29ybGQ="); -}); - -Deno.test("readFileEncodeAsString", function () { - const data = readFileSync(testData, "utf8"); - assertEquals(typeof data, "string"); - assertEquals(data as string, "hello world"); -}); - -Deno.test("[std/node/fs] readFile callback isn't called twice if error is thrown", async () => { - const tempFile = await Deno.makeTempFile(); - const importUrl = new URL("./_fs_readFile.ts", import.meta.url); - await assertCallbackErrorUncaught({ - prelude: `import { readFile } from ${JSON.stringify(importUrl)}`, - invocation: `readFile(${JSON.stringify(tempFile)}, `, - async cleanup() { - await Deno.remove(tempFile); - }, - }); -}); diff --git a/std/node/_fs/_fs_readdir.ts b/std/node/_fs/_fs_readdir.ts deleted file mode 100644 index e36bf5ecf..000000000 --- a/std/node/_fs/_fs_readdir.ts +++ /dev/null @@ -1,116 +0,0 @@ -import { asyncIterableToCallback } from "./_fs_watch.ts"; -import Dirent from "./_fs_dirent.ts"; -import { fromFileUrl } from "../path.ts"; - -function toDirent(val: Deno.DirEntry): Dirent { - return new Dirent(val); -} - -type readDirOptions = { - encoding?: string; - withFileTypes?: boolean; -}; - -type readDirCallback = (err: Error | null, files: string[]) => void; - -type readDirCallbackDirent = (err: Error | null, files: Dirent[]) => void; - -type readDirBoth = ( - ...args: [Error] | [null, string[] | Dirent[] | Array<string | Dirent>] -) => void; - -export function readdir( - path: string | URL, - options: { withFileTypes?: false; encoding?: string }, - callback: readDirCallback, -): void; -export function readdir( - path: string | URL, - options: { withFileTypes: true; encoding?: string }, - callback: readDirCallbackDirent, -): void; -export function readdir(path: string | URL, callback: readDirCallback): void; -export function readdir( - path: string | URL, - optionsOrCallback: readDirOptions | readDirCallback | readDirCallbackDirent, - maybeCallback?: readDirCallback | readDirCallbackDirent, -) { - const callback = - (typeof optionsOrCallback === "function" - ? optionsOrCallback - : maybeCallback) as readDirBoth | undefined; - const options = typeof optionsOrCallback === "object" - ? optionsOrCallback - : null; - const result: Array<string | Dirent> = []; - path = path instanceof URL ? fromFileUrl(path) : path; - - if (!callback) throw new Error("No callback function supplied"); - - if (options?.encoding) { - try { - new TextDecoder(options.encoding); - } catch (error) { - throw new Error( - `TypeError [ERR_INVALID_OPT_VALUE_ENCODING]: The value "${options.encoding}" is invalid for option "encoding"`, - ); - } - } - - try { - asyncIterableToCallback(Deno.readDir(path), (val, done) => { - if (typeof path !== "string") return; - if (done) { - callback(null, result); - return; - } - if (options?.withFileTypes) { - result.push(toDirent(val)); - } else result.push(decode(val.name)); - }); - } catch (error) { - callback(error); - } -} - -function decode(str: string, encoding?: string): string { - if (!encoding) return str; - else { - const decoder = new TextDecoder(encoding); - const encoder = new TextEncoder(); - return decoder.decode(encoder.encode(str)); - } -} - -export function readdirSync( - path: string | URL, - options: { withFileTypes: true; encoding?: string }, -): Dirent[]; -export function readdirSync( - path: string | URL, - options?: { withFileTypes?: false; encoding?: string }, -): string[]; -export function readdirSync( - path: string | URL, - options?: readDirOptions, -): Array<string | Dirent> { - const result = []; - path = path instanceof URL ? fromFileUrl(path) : path; - - if (options?.encoding) { - try { - new TextDecoder(options.encoding); - } catch (error) { - throw new Error( - `TypeError [ERR_INVALID_OPT_VALUE_ENCODING]: The value "${options.encoding}" is invalid for option "encoding"`, - ); - } - } - - for (const file of Deno.readDirSync(path)) { - if (options?.withFileTypes) { - result.push(toDirent(file)); - } else result.push(decode(file.name)); - } - return result; -} diff --git a/std/node/_fs/_fs_readdir_test.ts b/std/node/_fs/_fs_readdir_test.ts deleted file mode 100644 index 165cb8141..000000000 --- a/std/node/_fs/_fs_readdir_test.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { assertEquals, assertNotEquals, fail } from "../../testing/asserts.ts"; -import { assertCallbackErrorUncaught } from "../_utils.ts"; -import { readdir, readdirSync } from "./_fs_readdir.ts"; -import { join } from "../../path/mod.ts"; - -Deno.test({ - name: "ASYNC: reading empty directory", - async fn() { - const dir = Deno.makeTempDirSync(); - await new Promise<string[]>((resolve, reject) => { - readdir(dir, (err, files) => { - if (err) reject(err); - resolve(files); - }); - }) - .then((files) => assertEquals(files, []), () => fail()) - .finally(() => Deno.removeSync(dir)); - }, -}); - -function assertEqualsArrayAnyOrder<T>(actual: T[], expected: T[]) { - assertEquals(actual.length, expected.length); - for (const item of expected) { - const index = actual.indexOf(item); - assertNotEquals(index, -1); - expected = expected.splice(index, 1); - } -} - -Deno.test({ - name: "ASYNC: reading non-empty directory", - async fn() { - const dir = Deno.makeTempDirSync(); - Deno.writeTextFileSync(join(dir, "file1.txt"), "hi"); - Deno.writeTextFileSync(join(dir, "file2.txt"), "hi"); - Deno.mkdirSync(join(dir, "some_dir")); - await new Promise<string[]>((resolve, reject) => { - readdir(dir, (err, files) => { - if (err) reject(err); - resolve(files); - }); - }) - .then( - (files) => - assertEqualsArrayAnyOrder( - files, - ["file1.txt", "some_dir", "file2.txt"], - ), - () => fail(), - ) - .finally(() => Deno.removeSync(dir, { recursive: true })); - }, -}); - -Deno.test({ - name: "SYNC: reading empty the directory", - fn() { - const dir = Deno.makeTempDirSync(); - assertEquals(readdirSync(dir), []); - }, -}); - -Deno.test({ - name: "SYNC: reading non-empty directory", - fn() { - const dir = Deno.makeTempDirSync(); - Deno.writeTextFileSync(join(dir, "file1.txt"), "hi"); - Deno.writeTextFileSync(join(dir, "file2.txt"), "hi"); - Deno.mkdirSync(join(dir, "some_dir")); - assertEqualsArrayAnyOrder( - readdirSync(dir), - ["file1.txt", "some_dir", "file2.txt"], - ); - }, -}); - -Deno.test("[std/node/fs] readdir callback isn't called twice if error is thrown", async () => { - // The correct behaviour is not to catch any errors thrown, - // but that means there'll be an uncaught error and the test will fail. - // So the only way to test this is to spawn a subprocess, and succeed if it has a non-zero exit code. - // (assertThrowsAsync won't work because there's no way to catch the error.) - const tempDir = await Deno.makeTempDir(); - const importUrl = new URL("./_fs_readdir.ts", import.meta.url); - await assertCallbackErrorUncaught({ - prelude: `import { readdir } from ${JSON.stringify(importUrl)}`, - invocation: `readdir(${JSON.stringify(tempDir)}, `, - async cleanup() { - await Deno.remove(tempDir); - }, - }); -}); diff --git a/std/node/_fs/_fs_readlink.ts b/std/node/_fs/_fs_readlink.ts deleted file mode 100644 index 37a7a108f..000000000 --- a/std/node/_fs/_fs_readlink.ts +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import { - intoCallbackAPIWithIntercept, - MaybeEmpty, - notImplemented, -} from "../_utils.ts"; -import { fromFileUrl } from "../path.ts"; - -type ReadlinkCallback = ( - err: MaybeEmpty<Error>, - linkString: MaybeEmpty<string | Uint8Array>, -) => void; - -interface ReadlinkOptions { - encoding?: string | null; -} - -function maybeEncode( - data: string, - encoding: string | null, -): string | Uint8Array { - if (encoding === "buffer") { - return new TextEncoder().encode(data); - } - return data; -} - -function getEncoding( - optOrCallback?: ReadlinkOptions | ReadlinkCallback, -): string | null { - if (!optOrCallback || typeof optOrCallback === "function") { - return null; - } else { - if (optOrCallback.encoding) { - if ( - optOrCallback.encoding === "utf8" || - optOrCallback.encoding === "utf-8" - ) { - return "utf8"; - } else if (optOrCallback.encoding === "buffer") { - return "buffer"; - } else { - notImplemented(); - } - } - return null; - } -} - -export function readlink( - path: string | URL, - optOrCallback: ReadlinkCallback | ReadlinkOptions, - callback?: ReadlinkCallback, -): void { - path = path instanceof URL ? fromFileUrl(path) : path; - - let cb: ReadlinkCallback | undefined; - if (typeof optOrCallback === "function") { - cb = optOrCallback; - } else { - cb = callback; - } - - const encoding = getEncoding(optOrCallback); - - intoCallbackAPIWithIntercept<string, Uint8Array | string>( - Deno.readLink, - (data: string): string | Uint8Array => maybeEncode(data, encoding), - cb, - path, - ); -} - -export function readlinkSync( - path: string | URL, - opt?: ReadlinkOptions, -): string | Uint8Array { - path = path instanceof URL ? fromFileUrl(path) : path; - - return maybeEncode(Deno.readLinkSync(path), getEncoding(opt)); -} diff --git a/std/node/_fs/_fs_readlink_test.ts b/std/node/_fs/_fs_readlink_test.ts deleted file mode 100644 index cb3dd25b4..000000000 --- a/std/node/_fs/_fs_readlink_test.ts +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import { assertCallbackErrorUncaught } from "../_utils.ts"; -import { readlink, readlinkSync } from "./_fs_readlink.ts"; -import { assert, assertEquals } from "../../testing/asserts.ts"; -import * as path from "../path.ts"; - -const testDir = Deno.makeTempDirSync(); -const oldname = path.join(testDir, "oldname"); -const newname = path.join(testDir, "newname"); - -if (Deno.build.os === "windows") { - Deno.symlinkSync(oldname, newname, { type: "file" }); -} else { - Deno.symlinkSync(oldname, newname); -} - -Deno.test({ - name: "readlinkSuccess", - async fn() { - const data = await new Promise((res, rej) => { - readlink(newname, (err, data) => { - if (err) { - rej(err); - } - res(data); - }); - }); - - assertEquals(typeof data, "string"); - assertEquals(data as string, oldname); - }, -}); - -Deno.test({ - name: "readlinkEncodeBufferSuccess", - async fn() { - const data = await new Promise((res, rej) => { - readlink(newname, { encoding: "buffer" }, (err, data) => { - if (err) { - rej(err); - } - res(data); - }); - }); - - assert(data instanceof Uint8Array); - assertEquals(new TextDecoder().decode(data as Uint8Array), oldname); - }, -}); - -Deno.test({ - name: "readlinkSyncSuccess", - fn() { - const data = readlinkSync(newname); - assertEquals(typeof data, "string"); - assertEquals(data as string, oldname); - }, -}); - -Deno.test({ - name: "readlinkEncodeBufferSuccess", - fn() { - const data = readlinkSync(newname, { encoding: "buffer" }); - assert(data instanceof Uint8Array); - assertEquals(new TextDecoder().decode(data as Uint8Array), oldname); - }, -}); - -Deno.test("[std/node/fs] readlink callback isn't called twice if error is thrown", async () => { - const importUrl = new URL("./_fs_readlink.ts", import.meta.url); - await assertCallbackErrorUncaught({ - prelude: `import { readlink } from ${JSON.stringify(importUrl)}`, - invocation: `readlink(${JSON.stringify(newname)}, `, - }); -}); diff --git a/std/node/_fs/_fs_realpath.ts b/std/node/_fs/_fs_realpath.ts deleted file mode 100644 index 95e699d65..000000000 --- a/std/node/_fs/_fs_realpath.ts +++ /dev/null @@ -1,23 +0,0 @@ -type Options = { encoding: string }; -type Callback = (err: Error | null, path?: string) => void; - -export function realpath( - path: string, - options?: Options | Callback, - callback?: Callback, -) { - if (typeof options === "function") { - callback = options; - } - if (!callback) { - throw new Error("No callback function supplied"); - } - Deno.realPath(path).then( - (path) => callback!(null, path), - (err) => callback!(err), - ); -} - -export function realpathSync(path: string): string { - return Deno.realPathSync(path); -} diff --git a/std/node/_fs/_fs_realpath_test.ts b/std/node/_fs/_fs_realpath_test.ts deleted file mode 100644 index 08eb3ef16..000000000 --- a/std/node/_fs/_fs_realpath_test.ts +++ /dev/null @@ -1,54 +0,0 @@ -import * as path from "../../path/mod.ts"; -import { assertEquals } from "../../testing/asserts.ts"; -import { assertCallbackErrorUncaught } from "../_utils.ts"; -import { realpath, realpathSync } from "./_fs_realpath.ts"; - -Deno.test("realpath", async function () { - const tempFile = await Deno.makeTempFile(); - const tempFileAlias = tempFile + ".alias"; - await Deno.symlink(tempFile, tempFileAlias); - const realPath = await new Promise((resolve, reject) => { - realpath(tempFile, (err, path) => { - if (err) { - reject(err); - return; - } - resolve(path); - }); - }); - const realSymLinkPath = await new Promise((resolve, reject) => { - realpath(tempFileAlias, (err, path) => { - if (err) { - reject(err); - return; - } - resolve(path); - }); - }); - assertEquals(realPath, realSymLinkPath); -}); - -Deno.test("realpathSync", function () { - const tempFile = Deno.makeTempFileSync(); - const tempFileAlias = tempFile + ".alias"; - Deno.symlinkSync(tempFile, tempFileAlias); - const realPath = realpathSync(tempFile); - const realSymLinkPath = realpathSync(tempFileAlias); - assertEquals(realPath, realSymLinkPath); -}); - -Deno.test("[std/node/fs] realpath callback isn't called twice if error is thrown", async () => { - const tempDir = await Deno.makeTempDir(); - const tempFile = path.join(tempDir, "file.txt"); - const linkFile = path.join(tempDir, "link.txt"); - await Deno.writeTextFile(tempFile, "hello world"); - await Deno.symlink(tempFile, linkFile, { type: "file" }); - const importUrl = new URL("./_fs_realpath.ts", import.meta.url); - await assertCallbackErrorUncaught({ - prelude: `import { realpath } from ${JSON.stringify(importUrl)}`, - invocation: `realpath(${JSON.stringify(`${tempDir}/link.txt`)}, `, - async cleanup() { - await Deno.remove(tempDir, { recursive: true }); - }, - }); -}); diff --git a/std/node/_fs/_fs_rename.ts b/std/node/_fs/_fs_rename.ts deleted file mode 100644 index b121eacf9..000000000 --- a/std/node/_fs/_fs_rename.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { fromFileUrl } from "../path.ts"; - -export function rename( - oldPath: string | URL, - newPath: string | URL, - callback: (err?: Error) => void, -) { - oldPath = oldPath instanceof URL ? fromFileUrl(oldPath) : oldPath; - newPath = newPath instanceof URL ? fromFileUrl(newPath) : newPath; - - if (!callback) throw new Error("No callback function supplied"); - - Deno.rename(oldPath, newPath).then((_) => callback(), callback); -} - -export function renameSync(oldPath: string | URL, newPath: string | URL) { - oldPath = oldPath instanceof URL ? fromFileUrl(oldPath) : oldPath; - newPath = newPath instanceof URL ? fromFileUrl(newPath) : newPath; - - Deno.renameSync(oldPath, newPath); -} diff --git a/std/node/_fs/_fs_rename_test.ts b/std/node/_fs/_fs_rename_test.ts deleted file mode 100644 index e35e5282e..000000000 --- a/std/node/_fs/_fs_rename_test.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { assertEquals, fail } from "../../testing/asserts.ts"; -import { assertCallbackErrorUncaught } from "../_utils.ts"; -import { rename, renameSync } from "./_fs_rename.ts"; -import { existsSync } from "../../fs/mod.ts"; -import { join, parse } from "../../path/mod.ts"; - -Deno.test({ - name: "ASYNC: renaming a file", - async fn() { - const file = Deno.makeTempFileSync(); - const newPath = join(parse(file).dir, `${parse(file).base}_renamed`); - await new Promise<void>((resolve, reject) => { - rename(file, newPath, (err) => { - if (err) reject(err); - resolve(); - }); - }) - .then(() => { - assertEquals(existsSync(newPath), true); - assertEquals(existsSync(file), false); - }, () => fail()) - .finally(() => { - if (existsSync(file)) Deno.removeSync(file); - if (existsSync(newPath)) Deno.removeSync(newPath); - }); - }, -}); - -Deno.test({ - name: "SYNC: renaming a file", - fn() { - const file = Deno.makeTempFileSync(); - const newPath = join(parse(file).dir, `${parse(file).base}_renamed`); - renameSync(file, newPath); - assertEquals(existsSync(newPath), true); - assertEquals(existsSync(file), false); - }, -}); - -Deno.test("[std/node/fs] rename callback isn't called twice if error is thrown", async () => { - const tempFile = await Deno.makeTempFile(); - const importUrl = new URL("./_fs_rename.ts", import.meta.url); - await assertCallbackErrorUncaught({ - prelude: `import { rename } from ${JSON.stringify(importUrl)}`, - invocation: `rename(${JSON.stringify(tempFile)}, - ${JSON.stringify(`${tempFile}.newname`)}, `, - async cleanup() { - await Deno.remove(`${tempFile}.newname`); - }, - }); -}); diff --git a/std/node/_fs/_fs_rmdir.ts b/std/node/_fs/_fs_rmdir.ts deleted file mode 100644 index e82e696e3..000000000 --- a/std/node/_fs/_fs_rmdir.ts +++ /dev/null @@ -1,35 +0,0 @@ -type rmdirOptions = { - maxRetries?: number; - recursive?: boolean; - retryDelay?: number; -}; - -type rmdirCallback = (err?: Error) => void; - -export function rmdir(path: string | URL, callback: rmdirCallback): void; -export function rmdir( - path: string | URL, - options: rmdirOptions, - callback: rmdirCallback, -): void; -export function rmdir( - path: string | URL, - optionsOrCallback: rmdirOptions | rmdirCallback, - maybeCallback?: rmdirCallback, -) { - const callback = typeof optionsOrCallback === "function" - ? optionsOrCallback - : maybeCallback; - const options = typeof optionsOrCallback === "object" - ? optionsOrCallback - : undefined; - - if (!callback) throw new Error("No callback function supplied"); - - Deno.remove(path, { recursive: options?.recursive }) - .then((_) => callback(), callback); -} - -export function rmdirSync(path: string | URL, options?: rmdirOptions) { - Deno.removeSync(path, { recursive: options?.recursive }); -} diff --git a/std/node/_fs/_fs_rmdir_test.ts b/std/node/_fs/_fs_rmdir_test.ts deleted file mode 100644 index 6f9c33274..000000000 --- a/std/node/_fs/_fs_rmdir_test.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { assertEquals, fail } from "../../testing/asserts.ts"; -import { rmdir, rmdirSync } from "./_fs_rmdir.ts"; -import { closeSync } from "./_fs_close.ts"; -import { existsSync } from "../../fs/mod.ts"; -import { join } from "../../path/mod.ts"; -import { assertCallbackErrorUncaught } from "../_utils.ts"; - -Deno.test({ - name: "ASYNC: removing empty folder", - async fn() { - const dir = Deno.makeTempDirSync(); - await new Promise<void>((resolve, reject) => { - rmdir(dir, (err) => { - if (err) reject(err); - resolve(); - }); - }) - .then(() => assertEquals(existsSync(dir), false), () => fail()) - .finally(() => { - if (existsSync(dir)) Deno.removeSync(dir); - }); - }, -}); - -Deno.test({ - name: "SYNC: removing empty folder", - fn() { - const dir = Deno.makeTempDirSync(); - rmdirSync(dir); - assertEquals(existsSync(dir), false); - }, -}); - -function closeRes(before: Deno.ResourceMap, after: Deno.ResourceMap) { - for (const key in after) { - if (!before[key]) { - try { - closeSync(Number(key)); - } catch (error) { - return error; - } - } - } -} - -Deno.test({ - name: "ASYNC: removing non-empty folder", - async fn() { - const rBefore = Deno.resources(); - const dir = Deno.makeTempDirSync(); - Deno.createSync(join(dir, "file1.txt")); - Deno.createSync(join(dir, "file2.txt")); - Deno.mkdirSync(join(dir, "some_dir")); - Deno.createSync(join(dir, "some_dir", "file.txt")); - await new Promise<void>((resolve, reject) => { - rmdir(dir, { recursive: true }, (err) => { - if (err) reject(err); - resolve(); - }); - }) - .then(() => assertEquals(existsSync(dir), false), () => fail()) - .finally(() => { - if (existsSync(dir)) Deno.removeSync(dir, { recursive: true }); - const rAfter = Deno.resources(); - closeRes(rBefore, rAfter); - }); - }, - ignore: Deno.build.os === "windows", -}); - -Deno.test({ - name: "SYNC: removing non-empty folder", - fn() { - const rBefore = Deno.resources(); - const dir = Deno.makeTempDirSync(); - Deno.createSync(join(dir, "file1.txt")); - Deno.createSync(join(dir, "file2.txt")); - Deno.mkdirSync(join(dir, "some_dir")); - Deno.createSync(join(dir, "some_dir", "file.txt")); - rmdirSync(dir, { recursive: true }); - assertEquals(existsSync(dir), false); - // closing resources - const rAfter = Deno.resources(); - closeRes(rBefore, rAfter); - }, - ignore: Deno.build.os === "windows", -}); - -Deno.test("[std/node/fs] rmdir callback isn't called twice if error is thrown", async () => { - // The correct behaviour is not to catch any errors thrown, - // but that means there'll be an uncaught error and the test will fail. - // So the only way to test this is to spawn a subprocess, and succeed if it has a non-zero exit code. - // (assertThrowsAsync won't work because there's no way to catch the error.) - const tempDir = await Deno.makeTempDir(); - const importUrl = new URL("./_fs_rmdir.ts", import.meta.url); - await assertCallbackErrorUncaught({ - prelude: `import { rmdir } from ${JSON.stringify(importUrl)}`, - invocation: `rmdir(${JSON.stringify(tempDir)}, `, - }); -}); diff --git a/std/node/_fs/_fs_stat.ts b/std/node/_fs/_fs_stat.ts deleted file mode 100644 index 4f7903d16..000000000 --- a/std/node/_fs/_fs_stat.ts +++ /dev/null @@ -1,289 +0,0 @@ -export type statOptions = { - bigint: 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(err), - ); -} - -export function statSync(path: string | URL): Stats; -export function statSync(path: string | URL, options: { bigint: false }): Stats; -export function statSync( - path: string | URL, - options: { bigint: true }, -): BigIntStats; -export function statSync( - path: string | URL, - options: statOptions = { bigint: false }, -): Stats | BigIntStats { - const origin = Deno.statSync(path); - return CFISBIS(origin, options.bigint); -} diff --git a/std/node/_fs/_fs_stat_test.ts b/std/node/_fs/_fs_stat_test.ts deleted file mode 100644 index 5a25cddcc..000000000 --- a/std/node/_fs/_fs_stat_test.ts +++ /dev/null @@ -1,130 +0,0 @@ -import { assertCallbackErrorUncaught } from "../_utils.ts"; -import { BigIntStats, stat, Stats, statSync } from "./_fs_stat.ts"; -import { assertEquals, fail } from "../../testing/asserts.ts"; - -export function assertStats(actual: Stats, expected: Deno.FileInfo) { - assertEquals(actual.dev, expected.dev); - assertEquals(actual.gid, expected.gid); - assertEquals(actual.size, expected.size); - assertEquals(actual.blksize, expected.blksize); - assertEquals(actual.blocks, expected.blocks); - assertEquals(actual.ino, expected.ino); - assertEquals(actual.gid, expected.gid); - assertEquals(actual.mode, expected.mode); - assertEquals(actual.nlink, expected.nlink); - assertEquals(actual.rdev, expected.rdev); - assertEquals(actual.uid, expected.uid); - assertEquals(actual.atime?.getTime(), expected.atime?.getTime()); - assertEquals(actual.mtime?.getTime(), expected.mtime?.getTime()); - assertEquals(actual.birthtime?.getTime(), expected.birthtime?.getTime()); - assertEquals(actual.atimeMs ?? undefined, expected.atime?.getTime()); - assertEquals(actual.mtimeMs ?? undefined, expected.mtime?.getTime()); - assertEquals(actual.birthtimeMs ?? undefined, expected.birthtime?.getTime()); - assertEquals(actual.isFile(), expected.isFile); - assertEquals(actual.isDirectory(), expected.isDirectory); - assertEquals(actual.isSymbolicLink(), expected.isSymlink); -} - -function toBigInt(num?: number | null) { - if (num === undefined || num === null) return null; - return BigInt(num); -} - -export function assertStatsBigInt( - actual: BigIntStats, - expected: Deno.FileInfo, -) { - assertEquals(actual.dev, toBigInt(expected.dev)); - assertEquals(actual.gid, toBigInt(expected.gid)); - assertEquals(actual.size, toBigInt(expected.size)); - assertEquals(actual.blksize, toBigInt(expected.blksize)); - assertEquals(actual.blocks, toBigInt(expected.blocks)); - assertEquals(actual.ino, toBigInt(expected.ino)); - assertEquals(actual.gid, toBigInt(expected.gid)); - assertEquals(actual.mode, toBigInt(expected.mode)); - assertEquals(actual.nlink, toBigInt(expected.nlink)); - assertEquals(actual.rdev, toBigInt(expected.rdev)); - assertEquals(actual.uid, toBigInt(expected.uid)); - assertEquals(actual.atime?.getTime(), expected.atime?.getTime()); - assertEquals(actual.mtime?.getTime(), expected.mtime?.getTime()); - assertEquals(actual.birthtime?.getTime(), expected.birthtime?.getTime()); - assertEquals( - actual.atimeMs === null ? undefined : Number(actual.atimeMs), - expected.atime?.getTime(), - ); - assertEquals( - actual.mtimeMs === null ? undefined : Number(actual.mtimeMs), - expected.mtime?.getTime(), - ); - assertEquals( - actual.birthtimeMs === null ? undefined : Number(actual.birthtimeMs), - expected.birthtime?.getTime(), - ); - assertEquals(actual.atimeNs === null, actual.atime === null); - assertEquals(actual.mtimeNs === null, actual.mtime === null); - assertEquals(actual.birthtimeNs === null, actual.birthtime === null); - assertEquals(actual.isFile(), expected.isFile); - assertEquals(actual.isDirectory(), expected.isDirectory); - assertEquals(actual.isSymbolicLink(), expected.isSymlink); -} - -Deno.test({ - name: "ASYNC: get a file Stats", - async fn() { - const file = Deno.makeTempFileSync(); - await new Promise<Stats>((resolve, reject) => { - stat(file, (err, stat) => { - if (err) reject(err); - resolve(stat); - }); - }) - .then((stat) => assertStats(stat, Deno.statSync(file)), () => fail()) - .finally(() => Deno.removeSync(file)); - }, -}); - -Deno.test({ - name: "SYNC: get a file Stats", - fn() { - const file = Deno.makeTempFileSync(); - assertStats(statSync(file), Deno.statSync(file)); - }, -}); - -Deno.test({ - name: "ASYNC: get a file BigInt Stats", - async fn() { - const file = Deno.makeTempFileSync(); - await new Promise<BigIntStats>((resolve, reject) => { - stat(file, { bigint: true }, (err, stat) => { - if (err) reject(err); - resolve(stat); - }); - }) - .then( - (stat) => assertStatsBigInt(stat, Deno.statSync(file)), - () => fail(), - ) - .finally(() => Deno.removeSync(file)); - }, -}); - -Deno.test({ - name: "SYNC: get a file BigInt Stats", - fn() { - const file = Deno.makeTempFileSync(); - assertStatsBigInt(statSync(file, { bigint: true }), Deno.statSync(file)); - }, -}); - -Deno.test("[std/node/fs] stat callback isn't called twice if error is thrown", async () => { - const tempFile = await Deno.makeTempFile(); - const importUrl = new URL("./_fs_stat.ts", import.meta.url); - await assertCallbackErrorUncaught({ - prelude: `import { stat } from ${JSON.stringify(importUrl)}`, - invocation: `stat(${JSON.stringify(tempFile)}, `, - async cleanup() { - await Deno.remove(tempFile); - }, - }); -}); diff --git a/std/node/_fs/_fs_unlink.ts b/std/node/_fs/_fs_unlink.ts deleted file mode 100644 index 7349bee46..000000000 --- a/std/node/_fs/_fs_unlink.ts +++ /dev/null @@ -1,8 +0,0 @@ -export function unlink(path: string | URL, callback: (err?: Error) => void) { - if (!callback) throw new Error("No callback function supplied"); - Deno.remove(path).then((_) => callback(), callback); -} - -export function unlinkSync(path: string | URL) { - Deno.removeSync(path); -} diff --git a/std/node/_fs/_fs_unlink_test.ts b/std/node/_fs/_fs_unlink_test.ts deleted file mode 100644 index 5021b1c38..000000000 --- a/std/node/_fs/_fs_unlink_test.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { assertEquals, fail } from "../../testing/asserts.ts"; -import { existsSync } from "../../fs/mod.ts"; -import { assertCallbackErrorUncaught } from "../_utils.ts"; -import { unlink, unlinkSync } from "./_fs_unlink.ts"; - -Deno.test({ - name: "ASYNC: deleting a file", - async fn() { - const file = Deno.makeTempFileSync(); - await new Promise<void>((resolve, reject) => { - unlink(file, (err) => { - if (err) reject(err); - resolve(); - }); - }) - .then(() => assertEquals(existsSync(file), false), () => fail()) - .finally(() => { - if (existsSync(file)) Deno.removeSync(file); - }); - }, -}); - -Deno.test({ - name: "SYNC: Test deleting a file", - fn() { - const file = Deno.makeTempFileSync(); - unlinkSync(file); - assertEquals(existsSync(file), false); - }, -}); - -Deno.test("[std/node/fs] unlink callback isn't called twice if error is thrown", async () => { - const tempFile = await Deno.makeTempFile(); - const importUrl = new URL("./_fs_unlink.ts", import.meta.url); - await assertCallbackErrorUncaught({ - prelude: `import { unlink } from ${JSON.stringify(importUrl)}`, - invocation: `unlink(${JSON.stringify(tempFile)}, `, - }); -}); diff --git a/std/node/_fs/_fs_watch.ts b/std/node/_fs/_fs_watch.ts deleted file mode 100644 index a5f3bb9c1..000000000 --- a/std/node/_fs/_fs_watch.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { fromFileUrl } from "../path.ts"; -import { EventEmitter } from "../events.ts"; -import { notImplemented } from "../_utils.ts"; - -export function asyncIterableIteratorToCallback<T>( - iterator: AsyncIterableIterator<T>, - callback: (val: T, done?: boolean) => void, -) { - function next() { - iterator.next().then((obj) => { - if (obj.done) { - callback(obj.value, true); - return; - } - callback(obj.value); - next(); - }); - } - next(); -} - -export function asyncIterableToCallback<T>( - iter: AsyncIterable<T>, - callback: (val: T, done?: boolean) => void, -) { - const iterator = iter[Symbol.asyncIterator](); - function next() { - iterator.next().then((obj) => { - if (obj.done) { - callback(obj.value, true); - return; - } - callback(obj.value); - next(); - }); - } - next(); -} - -type watchOptions = { - persistent?: boolean; - recursive?: boolean; - encoding?: string; -}; - -type watchListener = (eventType: string, filename: string) => void; - -export function watch( - filename: string | URL, - options: watchOptions, - listener: watchListener, -): FSWatcher; -export function watch( - filename: string | URL, - listener: watchListener, -): FSWatcher; -export function watch( - filename: string | URL, - options: watchOptions, -): FSWatcher; -export function watch(filename: string | URL): FSWatcher; -export function watch( - filename: string | URL, - optionsOrListener?: watchOptions | watchListener, - optionsOrListener2?: watchOptions | watchListener, -) { - const listener = typeof optionsOrListener === "function" - ? optionsOrListener - : typeof optionsOrListener2 === "function" - ? optionsOrListener2 - : undefined; - const options = typeof optionsOrListener === "object" - ? optionsOrListener - : typeof optionsOrListener2 === "object" - ? optionsOrListener2 - : undefined; - filename = filename instanceof URL ? fromFileUrl(filename) : filename; - - const iterator = Deno.watchFs(filename, { - recursive: options?.recursive || false, - }); - - if (!listener) throw new Error("No callback function supplied"); - - const fsWatcher = new FSWatcher(() => { - if (iterator.return) iterator.return(); - }); - - fsWatcher.on("change", listener); - - asyncIterableIteratorToCallback<Deno.FsEvent>(iterator, (val, done) => { - if (done) return; - fsWatcher.emit("change", val.kind, val.paths[0]); - }); - - return fsWatcher; -} - -class FSWatcher extends EventEmitter { - close: () => void; - constructor(closer: () => void) { - super(); - this.close = closer; - } - ref() { - notImplemented("FSWatcher.ref() is not implemented"); - } - unref() { - notImplemented("FSWatcher.unref() is not implemented"); - } -} diff --git a/std/node/_fs/_fs_watch_test.ts b/std/node/_fs/_fs_watch_test.ts deleted file mode 100644 index 00fce4ffd..000000000 --- a/std/node/_fs/_fs_watch_test.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { watch } from "./_fs_watch.ts"; -import { assertEquals, fail } from "../../testing/asserts.ts"; - -function wait(time: number) { - return new Promise((resolve) => { - setTimeout(resolve, time); - }); -} - -Deno.test({ - name: "watching a file", - async fn() { - const file = Deno.makeTempFileSync(); - const result: Array<[string, string]> = []; - const watcher = watch( - file, - (eventType, filename) => result.push([eventType, filename]), - ); - await wait(100); - Deno.writeTextFileSync(file, "something"); - await wait(100); - watcher.close(); - await wait(100); - assertEquals(result.length >= 1, true); - }, -}); diff --git a/std/node/_fs/_fs_writeFile.ts b/std/node/_fs/_fs_writeFile.ts deleted file mode 100644 index e68bd8884..000000000 --- a/std/node/_fs/_fs_writeFile.ts +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import { Encodings, notImplemented } from "../_utils.ts"; -import { fromFileUrl } from "../path.ts"; -import { Buffer } from "../buffer.ts"; -import { - CallbackWithError, - checkEncoding, - getEncoding, - getOpenOptions, - isFileOptions, - WriteFileOptions, -} from "./_fs_common.ts"; - -export function writeFile( - pathOrRid: string | number | URL, - data: string | Uint8Array, - optOrCallback: Encodings | CallbackWithError | WriteFileOptions | undefined, - callback?: CallbackWithError, -): void { - const callbackFn: CallbackWithError | undefined = - optOrCallback instanceof Function ? optOrCallback : callback; - const options: Encodings | WriteFileOptions | undefined = - optOrCallback instanceof Function ? undefined : optOrCallback; - - if (!callbackFn) { - throw new TypeError("Callback must be a function."); - } - - pathOrRid = pathOrRid instanceof URL ? fromFileUrl(pathOrRid) : pathOrRid; - - const flag: string | undefined = isFileOptions(options) - ? options.flag - : undefined; - - const mode: number | undefined = isFileOptions(options) - ? options.mode - : undefined; - - const encoding = checkEncoding(getEncoding(options)) || "utf8"; - const openOptions = getOpenOptions(flag || "w"); - - if (typeof data === "string") data = Buffer.from(data, encoding); - - const isRid = typeof pathOrRid === "number"; - let file; - - let error: Error | null = null; - (async (): Promise<void> => { - try { - file = isRid - ? new Deno.File(pathOrRid as number) - : await Deno.open(pathOrRid as string, openOptions); - - if (!isRid && mode) { - if (Deno.build.os === "windows") notImplemented(`"mode" on Windows`); - await Deno.chmod(pathOrRid as string, mode); - } - - await Deno.writeAll(file, data as Uint8Array); - } catch (e) { - error = e; - } finally { - // Make sure to close resource - if (!isRid && file) file.close(); - callbackFn(error); - } - })(); -} - -export function writeFileSync( - pathOrRid: string | number | URL, - data: string | Uint8Array, - options?: Encodings | WriteFileOptions, -): void { - pathOrRid = pathOrRid instanceof URL ? fromFileUrl(pathOrRid) : pathOrRid; - - const flag: string | undefined = isFileOptions(options) - ? options.flag - : undefined; - - const mode: number | undefined = isFileOptions(options) - ? options.mode - : undefined; - - const encoding = checkEncoding(getEncoding(options)) || "utf8"; - const openOptions = getOpenOptions(flag || "w"); - - if (typeof data === "string") data = Buffer.from(data, encoding); - - const isRid = typeof pathOrRid === "number"; - let file; - - let error: Error | null = null; - try { - file = isRid - ? new Deno.File(pathOrRid as number) - : Deno.openSync(pathOrRid as string, openOptions); - - if (!isRid && mode) { - if (Deno.build.os === "windows") notImplemented(`"mode" on Windows`); - Deno.chmodSync(pathOrRid as string, mode); - } - - Deno.writeAllSync(file, data as Uint8Array); - } catch (e) { - error = e; - } finally { - // Make sure to close resource - if (!isRid && file) file.close(); - - if (error) throw error; - } -} diff --git a/std/node/_fs/_fs_writeFile_test.ts b/std/node/_fs/_fs_writeFile_test.ts deleted file mode 100644 index 561f71f88..000000000 --- a/std/node/_fs/_fs_writeFile_test.ts +++ /dev/null @@ -1,310 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import { - assert, - assertEquals, - assertNotEquals, - assertThrows, -} from "../../testing/asserts.ts"; -import { writeFile, writeFileSync } from "./_fs_writeFile.ts"; -import type { TextEncodings } from "../_utils.ts"; -import * as path from "../../path/mod.ts"; - -const moduleDir = path.dirname(path.fromFileUrl(import.meta.url)); -const testDataDir = path.resolve(moduleDir, "testdata"); -const decoder = new TextDecoder("utf-8"); - -Deno.test("Callback must be a function error", function fn() { - assertThrows( - () => { - writeFile("some/path", "some data", "utf8"); - }, - TypeError, - "Callback must be a function.", - ); -}); - -Deno.test("Invalid encoding results in error()", function testEncodingErrors() { - assertThrows( - () => { - // @ts-expect-error Type '"made-up-encoding"' is not assignable to type - writeFile("some/path", "some data", "made-up-encoding", () => {}); - }, - Error, - `The value "made-up-encoding" is invalid for option "encoding"`, - ); - - assertThrows( - () => { - // @ts-expect-error Type '"made-up-encoding"' is not assignable to type - writeFileSync("some/path", "some data", "made-up-encoding"); - }, - Error, - `The value "made-up-encoding" is invalid for option "encoding"`, - ); - - assertThrows( - () => { - writeFile( - "some/path", - "some data", - { - // @ts-expect-error Type '"made-up-encoding"' is not assignable to type - encoding: "made-up-encoding", - }, - () => {}, - ); - }, - Error, - `The value "made-up-encoding" is invalid for option "encoding"`, - ); - - assertThrows( - () => { - writeFileSync("some/path", "some data", { - // @ts-expect-error Type '"made-up-encoding"' is not assignable to type - encoding: "made-up-encoding", - }); - }, - Error, - `The value "made-up-encoding" is invalid for option "encoding"`, - ); -}); - -Deno.test( - "Unsupported encoding results in error()", - function testUnsupportedEncoding() { - assertThrows( - () => { - writeFile("some/path", "some data", "utf16le", () => {}); - }, - Error, - `Not implemented: "utf16le" encoding`, - ); - - assertThrows( - () => { - writeFileSync("some/path", "some data", "utf16le"); - }, - Error, - `Not implemented: "utf16le" encoding`, - ); - }, -); - -Deno.test( - "Data is written to correct rid", - async function testCorrectWriteUsingRid() { - const tempFile: string = await Deno.makeTempFile(); - const file: Deno.File = await Deno.open(tempFile, { - create: true, - write: true, - read: true, - }); - - await new Promise<void>((resolve, reject) => { - writeFile(file.rid, "hello world", (err) => { - if (err) return reject(err); - resolve(); - }); - }); - Deno.close(file.rid); - - const data = await Deno.readFile(tempFile); - await Deno.remove(tempFile); - assertEquals(decoder.decode(data), "hello world"); - }, -); - -Deno.test( - "Data is written to correct file", - async function testCorrectWriteUsingPath() { - const res = await new Promise((resolve) => { - writeFile("_fs_writeFile_test_file.txt", "hello world", resolve); - }); - - const data = await Deno.readFile("_fs_writeFile_test_file.txt"); - await Deno.remove("_fs_writeFile_test_file.txt"); - assertEquals(res, null); - assertEquals(decoder.decode(data), "hello world"); - }, -); - -Deno.test( - "Data is written to correct file encodings", - async function testCorrectWriteUsingDifferentEncodings() { - const encodings = [ - ["hex", "68656c6c6f20776f726c64"], - ["HEX", "68656c6c6f20776f726c64"], - ["base64", "aGVsbG8gd29ybGQ="], - ["BASE64", "aGVsbG8gd29ybGQ="], - ["utf8", "hello world"], - ["utf-8", "hello world"], - ]; - - for (const [encoding, value] of encodings) { - const res = await new Promise((resolve) => { - writeFile( - "_fs_writeFile_test_file.txt", - value, - encoding as TextEncodings, - resolve, - ); - }); - - const data = await Deno.readFile("_fs_writeFile_test_file.txt"); - await Deno.remove("_fs_writeFile_test_file.txt"); - assertEquals(res, null); - assertEquals(decoder.decode(data), "hello world"); - } - }, -); - -Deno.test("Path can be an URL", async function testCorrectWriteUsingURL() { - const url = new URL( - Deno.build.os === "windows" - ? "file:///" + - path - .join(testDataDir, "_fs_writeFile_test_file_url.txt") - .replace(/\\/g, "/") - : "file://" + path.join(testDataDir, "_fs_writeFile_test_file_url.txt"), - ); - const filePath = path.fromFileUrl(url); - const res = await new Promise((resolve) => { - writeFile(url, "hello world", resolve); - }); - assert(res === null); - - const data = await Deno.readFile(filePath); - await Deno.remove(filePath); - assertEquals(res, null); - assertEquals(decoder.decode(data), "hello world"); -}); - -Deno.test("Mode is correctly set", async function testCorrectFileMode() { - if (Deno.build.os === "windows") return; - const filename = "_fs_writeFile_test_file.txt"; - - const res = await new Promise((resolve) => { - writeFile(filename, "hello world", { mode: 0o777 }, resolve); - }); - - const fileInfo = await Deno.stat(filename); - await Deno.remove(filename); - assertEquals(res, null); - assert(fileInfo && fileInfo.mode); - assertEquals(fileInfo.mode & 0o777, 0o777); -}); - -Deno.test( - "Mode is not set when rid is passed", - async function testCorrectFileModeRid() { - if (Deno.build.os === "windows") return; - - const filename: string = await Deno.makeTempFile(); - const file: Deno.File = await Deno.open(filename, { - create: true, - write: true, - read: true, - }); - - await new Promise<void>((resolve, reject) => { - writeFile(file.rid, "hello world", { mode: 0o777 }, (err) => { - if (err) return reject(err); - resolve(); - }); - }); - Deno.close(file.rid); - - const fileInfo = await Deno.stat(filename); - await Deno.remove(filename); - assert(fileInfo.mode); - assertNotEquals(fileInfo.mode & 0o777, 0o777); - }, -); - -Deno.test( - "Data is written synchronously to correct rid", - function testCorrectWriteSyncUsingRid() { - const tempFile: string = Deno.makeTempFileSync(); - const file: Deno.File = Deno.openSync(tempFile, { - create: true, - write: true, - read: true, - }); - - writeFileSync(file.rid, "hello world"); - Deno.close(file.rid); - - const data = Deno.readFileSync(tempFile); - Deno.removeSync(tempFile); - assertEquals(decoder.decode(data), "hello world"); - }, -); - -Deno.test( - "Data is written to correct file encodings", - function testCorrectWriteSyncUsingDifferentEncodings() { - const encodings = [ - ["hex", "68656c6c6f20776f726c64"], - ["HEX", "68656c6c6f20776f726c64"], - ["base64", "aGVsbG8gd29ybGQ="], - ["BASE64", "aGVsbG8gd29ybGQ="], - ["utf8", "hello world"], - ["utf-8", "hello world"], - ]; - - for (const [encoding, value] of encodings) { - const file = "_fs_writeFileSync_test_file"; - writeFileSync(file, value, encoding as TextEncodings); - - const data = Deno.readFileSync(file); - Deno.removeSync(file); - assertEquals(decoder.decode(data), "hello world"); - } - }, -); - -Deno.test( - "Data is written synchronously to correct file", - function testCorrectWriteSyncUsingPath() { - const file = "_fs_writeFileSync_test_file"; - - writeFileSync(file, "hello world"); - - const data = Deno.readFileSync(file); - Deno.removeSync(file); - assertEquals(decoder.decode(data), "hello world"); - }, -); - -Deno.test("sync: Path can be an URL", function testCorrectWriteSyncUsingURL() { - const filePath = path.join( - testDataDir, - "_fs_writeFileSync_test_file_url.txt", - ); - const url = new URL( - Deno.build.os === "windows" - ? "file:///" + filePath.replace(/\\/g, "/") - : "file://" + filePath, - ); - writeFileSync(url, "hello world"); - - const data = Deno.readFileSync(filePath); - Deno.removeSync(filePath); - assertEquals(decoder.decode(data), "hello world"); -}); - -Deno.test( - "Mode is correctly set when writing synchronously", - function testCorrectFileModeSync() { - if (Deno.build.os === "windows") return; - const filename = "_fs_writeFileSync_test_file.txt"; - - writeFileSync(filename, "hello world", { mode: 0o777 }); - - const fileInfo = Deno.statSync(filename); - Deno.removeSync(filename); - assert(fileInfo && fileInfo.mode); - assertEquals(fileInfo.mode & 0o777, 0o777); - }, -); diff --git a/std/node/_fs/promises/_fs_readFile.ts b/std/node/_fs/promises/_fs_readFile.ts deleted file mode 100644 index 3067b301f..000000000 --- a/std/node/_fs/promises/_fs_readFile.ts +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import type { - BinaryOptionsArgument, - FileOptionsArgument, - TextOptionsArgument, -} from "../_fs_common.ts"; -import { readFile as readFileCallback } from "../_fs_readFile.ts"; - -export function readFile( - path: string | URL, - options: TextOptionsArgument, -): Promise<string>; -export function readFile( - path: string | URL, - options?: BinaryOptionsArgument, -): Promise<Uint8Array>; -export function readFile( - path: string | URL, - options?: FileOptionsArgument, -): Promise<string | Uint8Array> { - return new Promise((resolve, reject) => { - readFileCallback(path, options, (err, data): void => { - if (err) return reject(err); - if (data == null) { - return reject(new Error("Invalid state: data missing, but no error")); - } - resolve(data); - }); - }); -} diff --git a/std/node/_fs/promises/_fs_readFile_test.ts b/std/node/_fs/promises/_fs_readFile_test.ts deleted file mode 100644 index 2810d1773..000000000 --- a/std/node/_fs/promises/_fs_readFile_test.ts +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import { readFile } from "./_fs_readFile.ts"; -import * as path from "../../../path/mod.ts"; -import { assert, assertEquals } from "../../../testing/asserts.ts"; - -const moduleDir = path.dirname(path.fromFileUrl(import.meta.url)); -const testData = path.resolve(moduleDir, "..", "testdata", "hello.txt"); - -Deno.test("readFileSuccess", async function () { - const data: Uint8Array = await readFile(testData); - - assert(data instanceof Uint8Array); - assertEquals(new TextDecoder().decode(data), "hello world"); -}); - -Deno.test("readFileBinarySuccess", async function () { - const data: Uint8Array = await readFile(testData, "binary"); - - assert(data instanceof Uint8Array); - assertEquals(new TextDecoder().decode(data), "hello world"); -}); - -Deno.test("readFileBinaryObjectSuccess", async function () { - const data: Uint8Array = await readFile(testData, { encoding: "binary" }); - - assert(data instanceof Uint8Array); - assertEquals(new TextDecoder().decode(data), "hello world"); -}); - -Deno.test("readFileStringObjectSuccess", async function () { - const data: string = await readFile(testData, { encoding: "utf8" }); - - assertEquals(typeof data, "string"); - assertEquals(data, "hello world"); -}); - -Deno.test("readFileEncodeHexSuccess", async function () { - const data: string = await readFile(testData, { encoding: "hex" }); - assertEquals(typeof data, "string"); - assertEquals(data as string, "68656c6c6f20776f726c64"); -}); - -Deno.test("readFileEncodeBase64Success", async function () { - const data: string = await readFile(testData, { encoding: "base64" }); - assertEquals(typeof data, "string"); - assertEquals(data as string, "aGVsbG8gd29ybGQ="); -}); - -Deno.test("readFileStringSuccess", async function () { - const data: string = await readFile(testData, "utf8"); - - assertEquals(typeof data, "string"); - assertEquals(data, "hello world"); -}); - -Deno.test("readFileError", async function () { - try { - await readFile("invalid-file", "utf8"); - } catch (e) { - assert(e instanceof Deno.errors.NotFound); - } -}); diff --git a/std/node/_fs/promises/_fs_writeFile.ts b/std/node/_fs/promises/_fs_writeFile.ts deleted file mode 100644 index 554b65d24..000000000 --- a/std/node/_fs/promises/_fs_writeFile.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import type { WriteFileOptions } from "../_fs_common.ts"; -import type { Encodings } from "../../_utils.ts"; - -import { writeFile as writeFileCallback } from "../_fs_writeFile.ts"; - -export function writeFile( - pathOrRid: string | number | URL, - data: string | Uint8Array, - options?: Encodings | WriteFileOptions, -): Promise<void> { - return new Promise((resolve, reject) => { - writeFileCallback(pathOrRid, data, options, (err?: Error | null) => { - if (err) return reject(err); - resolve(); - }); - }); -} diff --git a/std/node/_fs/promises/_fs_writeFile_test.ts b/std/node/_fs/promises/_fs_writeFile_test.ts deleted file mode 100644 index 644a416ca..000000000 --- a/std/node/_fs/promises/_fs_writeFile_test.ts +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. -import { - assert, - assertEquals, - assertNotEquals, - assertThrowsAsync, -} from "../../../testing/asserts.ts"; -import { writeFile } from "./_fs_writeFile.ts"; -import type { TextEncodings } from "../../_utils.ts"; - -const decoder = new TextDecoder("utf-8"); - -Deno.test("Invalid encoding results in error()", function testEncodingErrors() { - assertThrowsAsync( - async () => { - // @ts-expect-error Type '"made-up-encoding"' is not assignable to type - await writeFile("some/path", "some data", "made-up-encoding"); - }, - Error, - `The value "made-up-encoding" is invalid for option "encoding"`, - ); - assertThrowsAsync( - async () => { - await writeFile("some/path", "some data", { - // @ts-expect-error Type '"made-up-encoding"' is not assignable to type - encoding: "made-up-encoding", - }); - }, - Error, - `The value "made-up-encoding" is invalid for option "encoding"`, - ); -}); - -Deno.test( - "Unsupported encoding results in error()", - function testUnsupportedEncoding() { - assertThrowsAsync( - async () => { - await writeFile("some/path", "some data", "utf16le"); - }, - Error, - `Not implemented: "utf16le" encoding`, - ); - }, -); - -Deno.test( - "Data is written to correct rid", - async function testCorrectWriteUsingRid() { - const tempFile: string = await Deno.makeTempFile(); - const file: Deno.File = await Deno.open(tempFile, { - create: true, - write: true, - read: true, - }); - - await writeFile(file.rid, "hello world"); - Deno.close(file.rid); - - const data = await Deno.readFile(tempFile); - await Deno.remove(tempFile); - assertEquals(decoder.decode(data), "hello world"); - }, -); - -Deno.test( - "Data is written to correct file", - async function testCorrectWriteUsingPath() { - const openResourcesBeforeWrite: Deno.ResourceMap = Deno.resources(); - - await writeFile("_fs_writeFile_test_file.txt", "hello world"); - - assertEquals(Deno.resources(), openResourcesBeforeWrite); - const data = await Deno.readFile("_fs_writeFile_test_file.txt"); - await Deno.remove("_fs_writeFile_test_file.txt"); - assertEquals(decoder.decode(data), "hello world"); - }, -); - -Deno.test( - "Data is written to correct file encodings", - async function testCorrectWritePromiseUsingDifferentEncodings() { - const encodings = [ - ["hex", "68656c6c6f20776f726c64"], - ["HEX", "68656c6c6f20776f726c64"], - ["base64", "aGVsbG8gd29ybGQ="], - ["BASE64", "aGVsbG8gd29ybGQ="], - ["utf8", "hello world"], - ["utf-8", "hello world"], - ]; - - for (const [encoding, value] of encodings) { - await writeFile( - "_fs_writeFile_test_file.txt", - value, - encoding as TextEncodings, - ); - - const data = await Deno.readFile("_fs_writeFile_test_file.txt"); - await Deno.remove("_fs_writeFile_test_file.txt"); - assertEquals(decoder.decode(data), "hello world"); - } - }, -); - -Deno.test("Mode is correctly set", async function testCorrectFileMode() { - if (Deno.build.os === "windows") return; - const filename = "_fs_writeFile_test_file.txt"; - await writeFile(filename, "hello world", { mode: 0o777 }); - - const fileInfo = await Deno.stat(filename); - await Deno.remove(filename); - assert(fileInfo && fileInfo.mode); - assertEquals(fileInfo.mode & 0o777, 0o777); -}); - -Deno.test( - "Mode is not set when rid is passed", - async function testCorrectFileModeRid() { - if (Deno.build.os === "windows") return; - - const filename: string = await Deno.makeTempFile(); - const file: Deno.File = await Deno.open(filename, { - create: true, - write: true, - read: true, - }); - - await writeFile(file.rid, "hello world", { mode: 0o777 }); - Deno.close(file.rid); - - const fileInfo = await Deno.stat(filename); - await Deno.remove(filename); - assert(fileInfo.mode); - assertNotEquals(fileInfo.mode & 0o777, 0o777); - }, -); diff --git a/std/node/_fs/promises/mod.ts b/std/node/_fs/promises/mod.ts deleted file mode 100644 index 4cc6462b9..000000000 --- a/std/node/_fs/promises/mod.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { writeFile } from "./_fs_writeFile.ts"; -export { readFile } from "./_fs_readFile.ts"; diff --git a/std/node/_fs/testdata/hello.txt b/std/node/_fs/testdata/hello.txt deleted file mode 100644 index 95d09f2b1..000000000 --- a/std/node/_fs/testdata/hello.txt +++ /dev/null @@ -1 +0,0 @@ -hello world
\ No newline at end of file |