From 983c745d4f385594638c42c107dca7d55afd0731 Mon Sep 17 00:00:00 2001 From: Asher Gomez Date: Mon, 22 Jan 2024 10:20:59 +1100 Subject: [PATCH] chore: use `FsFile[Symbol.dispose]()` (#22007) This change takes advantage of explicit resources management for `FsFile` instances and tweaks documentation to encourage the use of it. --------- Signed-off-by: Asher Gomez --- cli/bench/deno_common.js | 3 +- cli/tests/unit/files_test.ts | 77 +++++++++---------------- cli/tests/unit/http_test.ts | 3 +- cli/tests/unit/process_test.ts | 6 +- cli/tests/unit/serve_test.ts | 3 +- cli/tests/unit/utime_test.ts | 6 +- cli/tsc/dts/lib.deno.ns.d.ts | 100 +++++++++++++++++---------------- tools/node_compat/setup.ts | 3 +- 8 files changed, 86 insertions(+), 115 deletions(-) diff --git a/cli/bench/deno_common.js b/cli/bench/deno_common.js index b4319c8a3e..954b0f6318 100644 --- a/cli/bench/deno_common.js +++ b/cli/bench/deno_common.js @@ -39,8 +39,7 @@ Deno.bench("perf_now", { n: 5e5 }, () => { }); Deno.bench("open_file_sync", () => { - const file = Deno.openSync("./cli/bench/testdata/128k.bin"); - file.close(); + using _file = Deno.openSync("./cli/bench/testdata/128k.bin"); }); // A common "language feature", that should be fast diff --git a/cli/tests/unit/files_test.ts b/cli/tests/unit/files_test.ts index 0b9a104a8f..977d6463db 100644 --- a/cli/tests/unit/files_test.ts +++ b/cli/tests/unit/files_test.ts @@ -18,17 +18,16 @@ Deno.test(function filesStdioFileDescriptors() { Deno.test({ permissions: { read: true } }, async function filesCopyToStdout() { const filename = "cli/tests/testdata/assets/fixture.json"; - const file = await Deno.open(filename); + using file = await Deno.open(filename); assert(file.rid > 2); const bytesWritten = await copy(file, Deno.stdout); const fileSize = Deno.statSync(filename).size; assertEquals(bytesWritten, fileSize); - file.close(); }); Deno.test({ permissions: { read: true } }, async function filesIter() { const filename = "cli/tests/testdata/assets/hello.txt"; - const file = await Deno.open(filename); + using file = await Deno.open(filename); let totalSize = 0; for await (const buf of Deno.iter(file)) { @@ -36,14 +35,13 @@ Deno.test({ permissions: { read: true } }, async function filesIter() { } assertEquals(totalSize, 12); - file.close(); }); Deno.test( { permissions: { read: true } }, async function filesIterCustomBufSize() { const filename = "cli/tests/testdata/assets/hello.txt"; - const file = await Deno.open(filename); + using file = await Deno.open(filename); let totalSize = 0; let iterations = 0; @@ -54,13 +52,12 @@ Deno.test( assertEquals(totalSize, 12); assertEquals(iterations, 2); - file.close(); }, ); Deno.test({ permissions: { read: true } }, function filesIterSync() { const filename = "cli/tests/testdata/assets/hello.txt"; - const file = Deno.openSync(filename); + using file = Deno.openSync(filename); let totalSize = 0; for (const buf of Deno.iterSync(file)) { @@ -68,14 +65,13 @@ Deno.test({ permissions: { read: true } }, function filesIterSync() { } assertEquals(totalSize, 12); - file.close(); }); Deno.test( { permissions: { read: true } }, function filesIterSyncCustomBufSize() { const filename = "cli/tests/testdata/assets/hello.txt"; - const file = Deno.openSync(filename); + using file = Deno.openSync(filename); let totalSize = 0; let iterations = 0; @@ -86,7 +82,6 @@ Deno.test( assertEquals(totalSize, 12); assertEquals(iterations, 2); - file.close(); }, ); @@ -166,12 +161,11 @@ Deno.test( }, function openSyncMode() { const path = Deno.makeTempDirSync() + "/test_openSync.txt"; - const file = Deno.openSync(path, { + using _file = Deno.openSync(path, { write: true, createNew: true, mode: 0o626, }); - file.close(); const pathInfo = Deno.statSync(path); if (Deno.build.os !== "windows") { assertEquals(pathInfo.mode! & 0o777, 0o626 & ~Deno.umask()); @@ -185,12 +179,11 @@ Deno.test( }, async function openMode() { const path = (await Deno.makeTempDir()) + "/test_open.txt"; - const file = await Deno.open(path, { + using _file = await Deno.open(path, { write: true, createNew: true, mode: 0o626, }); - file.close(); const pathInfo = Deno.statSync(path); if (Deno.build.os !== "windows") { assertEquals(pathInfo.mode! & 0o777, 0o626 & ~Deno.umask()); @@ -209,12 +202,11 @@ Deno.test( Deno.build.os === "windows" ? "/" : "" }${tempDir}/test_open.txt`, ); - const file = Deno.openSync(fileUrl, { + using _file = Deno.openSync(fileUrl, { write: true, createNew: true, mode: 0o626, }); - file.close(); const pathInfo = Deno.statSync(fileUrl); if (Deno.build.os !== "windows") { assertEquals(pathInfo.mode! & 0o777, 0o626 & ~Deno.umask()); @@ -235,12 +227,11 @@ Deno.test( Deno.build.os === "windows" ? "/" : "" }${tempDir}/test_open.txt`, ); - const file = await Deno.open(fileUrl, { + using _file = await Deno.open(fileUrl, { write: true, createNew: true, mode: 0o626, }); - file.close(); const pathInfo = Deno.statSync(fileUrl); if (Deno.build.os !== "windows") { assertEquals(pathInfo.mode! & 0o777, 0o626 & ~Deno.umask()); @@ -314,7 +305,7 @@ Deno.test( truncate: true, create: true, }; - const file = await Deno.open(filename, w); + using file = await Deno.open(filename, w); // writing null should throw an error await assertRejects( @@ -323,7 +314,6 @@ Deno.test( await file.write(null as any); }, ); // TODO(bartlomieju): Check error kind when dispatch_minimal pipes errors properly - file.close(); await Deno.remove(tempDir, { recursive: true }); }, ); @@ -333,7 +323,7 @@ Deno.test( async function readNullBufferFailure() { const tempDir = Deno.makeTempDirSync(); const filename = tempDir + "hello.txt"; - const file = await Deno.open(filename, { + using file = await Deno.open(filename, { read: true, write: true, truncate: true, @@ -351,7 +341,6 @@ Deno.test( }, TypeError); // TODO(bartlomieju): Check error kind when dispatch_minimal pipes errors properly - file.close(); await Deno.remove(tempDir, { recursive: true }); }, ); @@ -529,7 +518,7 @@ Deno.test( const filename = tempDir + "hello.txt"; const data = encoder.encode("Hello world!\n"); - const file = await Deno.open(filename, { + using file = await Deno.open(filename, { write: true, truncate: true, create: true, @@ -551,7 +540,6 @@ Deno.test( assertEquals(seekPosition, cursorPosition); const result = await file.read(buf); assertEquals(result, 13); - file.close(); await Deno.remove(tempDir, { recursive: true }); }, @@ -559,7 +547,7 @@ Deno.test( Deno.test({ permissions: { read: true } }, async function seekStart() { const filename = "cli/tests/testdata/assets/hello.txt"; - const file = await Deno.open(filename); + using file = await Deno.open(filename); const seekPosition = 6; // Deliberately move 1 step forward await file.read(new Uint8Array(1)); // "H" @@ -571,12 +559,11 @@ Deno.test({ permissions: { read: true } }, async function seekStart() { await file.read(buf); const decoded = new TextDecoder().decode(buf); assertEquals(decoded, "world!"); - file.close(); }); Deno.test({ permissions: { read: true } }, async function seekStartBigInt() { const filename = "cli/tests/testdata/assets/hello.txt"; - const file = await Deno.open(filename); + using file = await Deno.open(filename); const seekPosition = 6n; // Deliberately move 1 step forward await file.read(new Uint8Array(1)); // "H" @@ -588,12 +575,11 @@ Deno.test({ permissions: { read: true } }, async function seekStartBigInt() { await file.read(buf); const decoded = new TextDecoder().decode(buf); assertEquals(decoded, "world!"); - file.close(); }); Deno.test({ permissions: { read: true } }, function seekSyncStart() { const filename = "cli/tests/testdata/assets/hello.txt"; - const file = Deno.openSync(filename); + using file = Deno.openSync(filename); const seekPosition = 6; // Deliberately move 1 step forward file.readSync(new Uint8Array(1)); // "H" @@ -605,12 +591,11 @@ Deno.test({ permissions: { read: true } }, function seekSyncStart() { file.readSync(buf); const decoded = new TextDecoder().decode(buf); assertEquals(decoded, "world!"); - file.close(); }); Deno.test({ permissions: { read: true } }, async function seekCurrent() { const filename = "cli/tests/testdata/assets/hello.txt"; - const file = await Deno.open(filename); + using file = await Deno.open(filename); // Deliberately move 1 step forward await file.read(new Uint8Array(1)); // "H" // Skipping "ello " @@ -622,12 +607,11 @@ Deno.test({ permissions: { read: true } }, async function seekCurrent() { await file.read(buf); const decoded = new TextDecoder().decode(buf); assertEquals(decoded, "world!"); - file.close(); }); Deno.test({ permissions: { read: true } }, function seekSyncCurrent() { const filename = "cli/tests/testdata/assets/hello.txt"; - const file = Deno.openSync(filename); + using file = Deno.openSync(filename); // Deliberately move 1 step forward file.readSync(new Uint8Array(1)); // "H" // Skipping "ello " @@ -639,12 +623,11 @@ Deno.test({ permissions: { read: true } }, function seekSyncCurrent() { file.readSync(buf); const decoded = new TextDecoder().decode(buf); assertEquals(decoded, "world!"); - file.close(); }); Deno.test({ permissions: { read: true } }, async function seekEnd() { const filename = "cli/tests/testdata/assets/hello.txt"; - const file = await Deno.open(filename); + using file = await Deno.open(filename); const seekPosition = -6; // seek from end of file that has 12 chars, 12 - 6 = 6 const cursorPosition = await file.seek(seekPosition, Deno.SeekMode.End); @@ -653,12 +636,11 @@ Deno.test({ permissions: { read: true } }, async function seekEnd() { await file.read(buf); const decoded = new TextDecoder().decode(buf); assertEquals(decoded, "world!"); - file.close(); }); Deno.test({ permissions: { read: true } }, function seekSyncEnd() { const filename = "cli/tests/testdata/assets/hello.txt"; - const file = Deno.openSync(filename); + using file = Deno.openSync(filename); const seekPosition = -6; // seek from end of file that has 12 chars, 12 - 6 = 6 const cursorPosition = file.seekSync(seekPosition, Deno.SeekMode.End); @@ -667,12 +649,11 @@ Deno.test({ permissions: { read: true } }, function seekSyncEnd() { file.readSync(buf); const decoded = new TextDecoder().decode(buf); assertEquals(decoded, "world!"); - file.close(); }); Deno.test({ permissions: { read: true } }, async function seekMode() { const filename = "cli/tests/testdata/assets/hello.txt"; - const file = await Deno.open(filename); + using file = await Deno.open(filename); await assertRejects( async () => { await file.seek(1, -1 as unknown as Deno.SeekMode); @@ -686,14 +667,13 @@ Deno.test({ permissions: { read: true } }, async function seekMode() { const buf = new Uint8Array(1); await file.read(buf); // "H" assertEquals(new TextDecoder().decode(buf), "H"); - file.close(); }); Deno.test( { permissions: { read: true, write: true } }, function fileTruncateSyncSuccess() { const filename = Deno.makeTempDirSync() + "/test_fileTruncateSync.txt"; - const file = Deno.openSync(filename, { + using file = Deno.openSync(filename, { create: true, read: true, write: true, @@ -706,7 +686,6 @@ Deno.test( file.truncateSync(-5); assertEquals(Deno.readFileSync(filename).byteLength, 0); - file.close(); Deno.removeSync(filename); }, ); @@ -715,7 +694,7 @@ Deno.test( { permissions: { read: true, write: true } }, async function fileTruncateSuccess() { const filename = Deno.makeTempDirSync() + "/test_fileTruncate.txt"; - const file = await Deno.open(filename, { + using file = await Deno.open(filename, { create: true, read: true, write: true, @@ -728,13 +707,12 @@ Deno.test( await file.truncate(-5); assertEquals((await Deno.readFile(filename)).byteLength, 0); - file.close(); await Deno.remove(filename); }, ); Deno.test({ permissions: { read: true } }, function fileStatSyncSuccess() { - const file = Deno.openSync("README.md"); + using file = Deno.openSync("README.md"); const fileInfo = file.statSync(); assert(fileInfo.isFile); assert(!fileInfo.isSymlink); @@ -744,12 +722,10 @@ Deno.test({ permissions: { read: true } }, function fileStatSyncSuccess() { assert(fileInfo.mtime); // The `birthtime` field is not available on Linux before kernel version 4.11. assert(fileInfo.birthtime || Deno.build.os === "linux"); - - file.close(); }); Deno.test(async function fileStatSuccess() { - const file = await Deno.open("README.md"); + using file = await Deno.open("README.md"); const fileInfo = await file.stat(); assert(fileInfo.isFile); assert(!fileInfo.isSymlink); @@ -759,8 +735,6 @@ Deno.test(async function fileStatSuccess() { assert(fileInfo.mtime); // The `birthtime` field is not available on Linux before kernel version 4.11. assert(fileInfo.birthtime || Deno.build.os === "linux"); - - file.close(); }); Deno.test({ permissions: { read: true } }, async function readableStream() { @@ -813,10 +787,9 @@ Deno.test( { permissions: { read: true, write: true } }, async function readTextFileNonUtf8() { const path = await Deno.makeTempFile(); - const file = await Deno.open(path, { write: true }); + using file = await Deno.open(path, { write: true }); await file.write(new TextEncoder().encode("hello ")); await file.write(new Uint8Array([0xC0])); - file.close(); const res = await Deno.readTextFile(path); const resSync = Deno.readTextFileSync(path); diff --git a/cli/tests/unit/http_test.ts b/cli/tests/unit/http_test.ts index fbbf4e13d4..7d1f8997d8 100644 --- a/cli/tests/unit/http_test.ts +++ b/cli/tests/unit/http_test.ts @@ -950,9 +950,8 @@ Deno.test( { permissions: { net: true, write: true, read: true } }, async function httpServerCorrectSizeResponse() { const tmpFile = await Deno.makeTempFile(); - const file = await Deno.open(tmpFile, { write: true, read: true }); + using file = await Deno.open(tmpFile, { write: true, read: true }); await file.write(new Uint8Array(70 * 1024).fill(1)); // 70kb sent in 64kb + 6kb chunks - file.close(); let httpConn: Deno.HttpConn; const listener = Deno.listen({ port: listenPort }); diff --git a/cli/tests/unit/process_test.ts b/cli/tests/unit/process_test.ts index cb5dd08154..0cc4e99aaf 100644 --- a/cli/tests/unit/process_test.ts +++ b/cli/tests/unit/process_test.ts @@ -361,7 +361,7 @@ Deno.test( async function runRedirectStdoutStderr() { const tempDir = await Deno.makeTempDir(); const fileName = tempDir + "/redirected_stdio.txt"; - const file = await Deno.open(fileName, { + using file = await Deno.open(fileName, { create: true, write: true, }); @@ -379,7 +379,6 @@ Deno.test( await p.status(); p.close(); - file.close(); const fileContents = await Deno.readFile(fileName); const decoder = new TextDecoder(); @@ -396,7 +395,7 @@ Deno.test( const tempDir = await Deno.makeTempDir(); const fileName = tempDir + "/redirected_stdio.txt"; await Deno.writeTextFile(fileName, "hello"); - const file = await Deno.open(fileName); + using file = await Deno.open(fileName); // deno-lint-ignore no-deprecated-deno-api const p = Deno.run({ @@ -411,7 +410,6 @@ Deno.test( const status = await p.status(); assertEquals(status.code, 0); p.close(); - file.close(); }, ); diff --git a/cli/tests/unit/serve_test.ts b/cli/tests/unit/serve_test.ts index 9226a9bd26..e188932acf 100644 --- a/cli/tests/unit/serve_test.ts +++ b/cli/tests/unit/serve_test.ts @@ -2567,10 +2567,9 @@ function makeTempData(size: number) { async function makeTempFile(size: number) { const tmpFile = await Deno.makeTempFile(); - const file = await Deno.open(tmpFile, { write: true, read: true }); + using file = await Deno.open(tmpFile, { write: true, read: true }); const data = makeTempData(size); await file.write(data); - file.close(); return await Deno.open(tmpFile, { write: true, read: true }); } diff --git a/cli/tests/unit/utime_test.ts b/cli/tests/unit/utime_test.ts index 2375f2d79a..02566bad6e 100644 --- a/cli/tests/unit/utime_test.ts +++ b/cli/tests/unit/utime_test.ts @@ -11,7 +11,7 @@ Deno.test( async function futimeSyncSuccess() { const testDir = await Deno.makeTempDir(); const filename = testDir + "/file.txt"; - const file = await Deno.open(filename, { + using file = await Deno.open(filename, { create: true, write: true, }); @@ -24,7 +24,6 @@ Deno.test( const fileInfo = Deno.statSync(filename); assertEquals(fileInfo.atime, new Date(atime * 1000)); assertEquals(fileInfo.mtime, new Date(mtime * 1000)); - file.close(); }, ); @@ -33,7 +32,7 @@ Deno.test( function futimeSyncSuccess() { const testDir = Deno.makeTempDirSync(); const filename = testDir + "/file.txt"; - const file = Deno.openSync(filename, { + using file = Deno.openSync(filename, { create: true, write: true, }); @@ -46,7 +45,6 @@ Deno.test( const fileInfo = Deno.statSync(filename); assertEquals(fileInfo.atime, new Date(atime * 1000)); assertEquals(fileInfo.mtime, new Date(mtime * 1000)); - file.close(); }, ); diff --git a/cli/tsc/dts/lib.deno.ns.d.ts b/cli/tsc/dts/lib.deno.ns.d.ts index af427fda28..8a7abd0e18 100644 --- a/cli/tsc/dts/lib.deno.ns.d.ts +++ b/cli/tsc/dts/lib.deno.ns.d.ts @@ -1174,11 +1174,10 @@ declare namespace Deno { * * ```ts * Deno.bench("foo", async (t) => { - * const file = await Deno.open("data.txt"); + * using file = await Deno.open("data.txt"); * t.start(); * // some operation on `file`... * t.end(); - * file.close(); * }); * ``` */ @@ -1846,8 +1845,17 @@ declare namespace Deno { /** Open a file and resolve to an instance of {@linkcode Deno.FsFile}. The * file does not need to previously exist if using the `create` or `createNew` - * open options. It is the caller's responsibility to close the file when - * finished with it. + * open options. The caller may have the resulting file automatically closed + * by the runtime once it's out of scope by declaring the file variable with + * the `using` keyword. + * + * ```ts + * using file = await Deno.open("/foo/bar.txt", { read: true, write: true }); + * // Do work with file + * ``` + * + * Alternatively, the caller may manually close the resource when finished with + * it. * * ```ts * const file = await Deno.open("/foo/bar.txt", { read: true, write: true }); @@ -1868,8 +1876,17 @@ declare namespace Deno { /** Synchronously open a file and return an instance of * {@linkcode Deno.FsFile}. The file does not need to previously exist if - * using the `create` or `createNew` open options. It is the caller's - * responsibility to close the file when finished with it. + * using the `create` or `createNew` open options. The caller may have the + * resulting file automatically closed by the runtime once it's out of scope + * by declaring the file variable with the `using` keyword. + * + * ```ts + * using file = Deno.openSync("/foo/bar.txt", { read: true, write: true }); + * // Do work with file + * ``` + * + * Alternatively, the caller may manually close the resource when finished with + * it. * * ```ts * const file = Deno.openSync("/foo/bar.txt", { read: true, write: true }); @@ -2021,7 +2038,7 @@ declare namespace Deno { * * ```ts * // Given file.rid pointing to file with "Hello world", which is 11 bytes long: - * const file = await Deno.open( + * using file = await Deno.open( * "hello.txt", * { read: true, write: true, truncate: true, create: true }, * ); @@ -2033,14 +2050,13 @@ declare namespace Deno { * const buf = new Uint8Array(100); * await file.read(buf); * console.log(new TextDecoder().decode(buf)); // "world" - * file.close(); * ``` * * The seek modes work as follows: * * ```ts * // Given file.rid pointing to file with "Hello world", which is 11 bytes long: - * const file = await Deno.open( + * using file = await Deno.open( * "hello.txt", * { read: true, write: true, truncate: true, create: true }, * ); @@ -2052,7 +2068,6 @@ declare namespace Deno { * console.log(await Deno.seek(file.rid, 2, Deno.SeekMode.Current)); // "8" * // Seek backwards 2 bytes from the end of the file * console.log(await Deno.seek(file.rid, -2, Deno.SeekMode.End)); // "9" (i.e. 11-2) - * file.close(); * ``` * * @category I/O @@ -2068,7 +2083,7 @@ declare namespace Deno { * start) is returned. * * ```ts - * const file = Deno.openSync( + * using file = Deno.openSync( * "hello.txt", * { read: true, write: true, truncate: true, create: true }, * ); @@ -2080,14 +2095,13 @@ declare namespace Deno { * const buf = new Uint8Array(100); * file.readSync(buf); * console.log(new TextDecoder().decode(buf)); // "world" - * file.close(); * ``` * * The seek modes work as follows: * * ```ts * // Given file.rid pointing to file with "Hello world", which is 11 bytes long: - * const file = Deno.openSync( + * using file = Deno.openSync( * "hello.txt", * { read: true, write: true, truncate: true, create: true }, * ); @@ -2099,7 +2113,6 @@ declare namespace Deno { * console.log(Deno.seekSync(file.rid, 2, Deno.SeekMode.Current)); // "8" * // Seek backwards 2 bytes from the end of the file * console.log(Deno.seekSync(file.rid, -2, Deno.SeekMode.End)); // "9" (i.e. 11-2) - * file.close(); * ``` * * @category I/O @@ -2192,6 +2205,15 @@ declare namespace Deno { * Deno.close(file.rid); * ``` * + * It is recommended to define the variable with the `using` keyword so the + * runtime will automatically close the resource when it goes out of scope. + * Doing so negates the need to manually close the resource. + * + * ```ts + * using file = await Deno.open("my_file.txt"); + * // do work with "file" object + * ``` + * * @category I/O */ export function close(rid: number): void; @@ -2202,14 +2224,13 @@ declare namespace Deno { * recommended over using the discreet functions within the `Deno` namespace. * * ```ts - * const file = await Deno.open("/foo/bar.txt", { read: true }); + * using file = await Deno.open("/foo/bar.txt", { read: true }); * const fileInfo = await file.stat(); * if (fileInfo.isFile) { * const buf = new Uint8Array(100); * const numberOfBytesRead = await file.read(buf); // 11 bytes * const text = new TextDecoder().decode(buf); // "hello world" * } - * file.close(); * ``` * * @category File System @@ -2232,7 +2253,7 @@ declare namespace Deno { * based APIs. * * ```ts - * const file = await Deno.open("my_file.txt", { read: true }); + * using file = await Deno.open("my_file.txt", { read: true }); * const decoder = new TextDecoder(); * for await (const chunk of file.readable) { * console.log(decoder.decode(chunk)); @@ -2246,13 +2267,12 @@ declare namespace Deno { * * ```ts * const items = ["hello", "world"]; - * const file = await Deno.open("my_file.txt", { write: true }); + * using file = await Deno.open("my_file.txt", { write: true }); * const encoder = new TextEncoder(); * const writer = file.writable.getWriter(); * for (const item of items) { * await writer.write(encoder.encode(item)); * } - * file.close(); * ``` */ readonly writable: WritableStream; @@ -2270,9 +2290,8 @@ declare namespace Deno { * ```ts * const encoder = new TextEncoder(); * const data = encoder.encode("Hello world"); - * const file = await Deno.open("/foo/bar.txt", { write: true }); + * using file = await Deno.open("/foo/bar.txt", { write: true }); * const bytesWritten = await file.write(data); // 11 - * file.close(); * ``` * * @category I/O @@ -2288,9 +2307,8 @@ declare namespace Deno { * ```ts * const encoder = new TextEncoder(); * const data = encoder.encode("Hello world"); - * const file = Deno.openSync("/foo/bar.txt", { write: true }); + * using file = Deno.openSync("/foo/bar.txt", { write: true }); * const bytesWritten = file.writeSync(data); // 11 - * file.close(); * ``` */ writeSync(p: Uint8Array): number; @@ -2300,21 +2318,19 @@ declare namespace Deno { * ### Truncate the entire file * * ```ts - * const file = await Deno.open("my_file.txt", { write: true }); + * using file = await Deno.open("my_file.txt", { write: true }); * await file.truncate(); - * file.close(); * ``` * * ### Truncate part of the file * * ```ts * // if "my_file.txt" contains the text "hello world": - * const file = await Deno.open("my_file.txt", { write: true }); + * using file = await Deno.open("my_file.txt", { write: true }); * await file.truncate(7); * const buf = new Uint8Array(100); * await file.read(buf); * const text = new TextDecoder().decode(buf); // "hello w" - * file.close(); * ``` */ truncate(len?: number): Promise; @@ -2325,21 +2341,19 @@ declare namespace Deno { * ### Truncate the entire file * * ```ts - * const file = Deno.openSync("my_file.txt", { write: true }); + * using file = Deno.openSync("my_file.txt", { write: true }); * file.truncateSync(); - * file.close(); * ``` * * ### Truncate part of the file * * ```ts * // if "my_file.txt" contains the text "hello world": - * const file = Deno.openSync("my_file.txt", { write: true }); + * using file = Deno.openSync("my_file.txt", { write: true }); * file.truncateSync(7); * const buf = new Uint8Array(100); * file.readSync(buf); * const text = new TextDecoder().decode(buf); // "hello w" - * file.close(); * ``` */ truncateSync(len?: number): void; @@ -2356,11 +2370,10 @@ declare namespace Deno { * * ```ts * // if "/foo/bar.txt" contains the text "hello world": - * const file = await Deno.open("/foo/bar.txt"); + * using file = await Deno.open("/foo/bar.txt"); * const buf = new Uint8Array(100); * const numberOfBytesRead = await file.read(buf); // 11 bytes * const text = new TextDecoder().decode(buf); // "hello world" - * file.close(); * ``` */ read(p: Uint8Array): Promise; @@ -2377,11 +2390,10 @@ declare namespace Deno { * * ```ts * // if "/foo/bar.txt" contains the text "hello world": - * const file = Deno.openSync("/foo/bar.txt"); + * using file = Deno.openSync("/foo/bar.txt"); * const buf = new Uint8Array(100); * const numberOfBytesRead = file.readSync(buf); // 11 bytes * const text = new TextDecoder().decode(buf); // "hello world" - * file.close(); * ``` */ readSync(p: Uint8Array): number | null; @@ -2390,7 +2402,7 @@ declare namespace Deno { * * ```ts * // Given file pointing to file with "Hello world", which is 11 bytes long: - * const file = await Deno.open( + * using file = await Deno.open( * "hello.txt", * { read: true, write: true, truncate: true, create: true }, * ); @@ -2402,7 +2414,6 @@ declare namespace Deno { * const buf = new Uint8Array(100); * await file.read(buf); * console.log(new TextDecoder().decode(buf)); // "world" - * file.close(); * ``` * * The seek modes work as follows: @@ -2428,7 +2439,7 @@ declare namespace Deno { * The new position within the resource (bytes from the start) is returned. * * ```ts - * const file = Deno.openSync( + * using file = Deno.openSync( * "hello.txt", * { read: true, write: true, truncate: true, create: true }, * ); @@ -2440,14 +2451,13 @@ declare namespace Deno { * const buf = new Uint8Array(100); * file.readSync(buf); * console.log(new TextDecoder().decode(buf)); // "world" - * file.close(); * ``` * * The seek modes work as follows: * * ```ts * // Given file.rid pointing to file with "Hello world", which is 11 bytes long: - * const file = Deno.openSync( + * using file = Deno.openSync( * "hello.txt", * { read: true, write: true, truncate: true, create: true }, * ); @@ -2459,7 +2469,6 @@ declare namespace Deno { * console.log(file.seekSync(2, Deno.SeekMode.Current)); // "8" * // Seek backwards 2 bytes from the end of the file * console.log(file.seekSync(-2, Deno.SeekMode.End)); // "9" (i.e. 11-2) - * file.close(); * ``` */ seekSync(offset: number | bigint, whence: SeekMode): number; @@ -2468,10 +2477,9 @@ declare namespace Deno { * ```ts * import { assert } from "https://deno.land/std/assert/mod.ts"; * - * const file = await Deno.open("hello.txt"); + * using file = await Deno.open("hello.txt"); * const fileInfo = await file.stat(); * assert(fileInfo.isFile); - * file.close(); * ``` */ stat(): Promise; @@ -2480,10 +2488,9 @@ declare namespace Deno { * ```ts * import { assert } from "https://deno.land/std/assert/mod.ts"; * - * const file = Deno.openSync("hello.txt") + * using file = Deno.openSync("hello.txt") * const fileInfo = file.statSync(); * assert(fileInfo.isFile); - * file.close(); * ``` */ statSync(): FileInfo; @@ -2491,9 +2498,8 @@ declare namespace Deno { * important to avoid leaking resources. * * ```ts - * const file = await Deno.open("my_file.txt"); + * using file = await Deno.open("my_file.txt"); * // do work with "file" object - * file.close(); * ``` */ close(): void; diff --git a/tools/node_compat/setup.ts b/tools/node_compat/setup.ts index 867953ef98..2844cffdd9 100755 --- a/tools/node_compat/setup.ts +++ b/tools/node_compat/setup.ts @@ -65,7 +65,7 @@ function getDenoTests() { } async function updateToDo() { - const file = await Deno.open(new URL("./TODO.md", import.meta.url), { + using file = await Deno.open(new URL("./TODO.md", import.meta.url), { write: true, create: true, truncate: true, @@ -88,7 +88,6 @@ Total: ${missingTests.length} ), ); } - file.close(); } async function clearTests() {