diff --git a/cli/tests/unit/read_file_test.ts b/cli/tests/unit/read_file_test.ts index 5594eb4ae3..5f8ee2c118 100644 --- a/cli/tests/unit/read_file_test.ts +++ b/cli/tests/unit/read_file_test.ts @@ -77,3 +77,21 @@ unitTest({ perms: { read: true } }, function readFileSyncLoop(): void { Deno.readFileSync("cli/tests/fixture.json"); } }); + +unitTest( + { perms: { read: true } }, + async function readFileDoesNotLeakResources(): Promise { + const resourcesBefore = Deno.resources(); + await assertThrowsAsync(async () => await Deno.readFile("cli")); + assertEquals(resourcesBefore, Deno.resources()); + }, +); + +unitTest( + { perms: { read: true } }, + function readFileSyncDoesNotLeakResources(): void { + const resourcesBefore = Deno.resources(); + assertThrows(() => Deno.readFileSync("cli")); + assertEquals(resourcesBefore, Deno.resources()); + }, +); diff --git a/cli/tests/unit/read_text_file_test.ts b/cli/tests/unit/read_text_file_test.ts index dc6a901bb6..2223d9c185 100644 --- a/cli/tests/unit/read_text_file_test.ts +++ b/cli/tests/unit/read_text_file_test.ts @@ -69,3 +69,21 @@ unitTest({ perms: { read: true } }, function readTextFileSyncLoop(): void { Deno.readTextFileSync("cli/tests/fixture.json"); } }); + +unitTest( + { perms: { read: true } }, + async function readTextFileDoesNotLeakResources(): Promise { + const resourcesBefore = Deno.resources(); + await assertThrowsAsync(async () => await Deno.readTextFile("cli")); + assertEquals(resourcesBefore, Deno.resources()); + }, +); + +unitTest( + { perms: { read: true } }, + function readTextFileSyncDoesNotLeakResources(): void { + const resourcesBefore = Deno.resources(); + assertThrows(() => Deno.readTextFileSync("cli")); + assertEquals(resourcesBefore, Deno.resources()); + }, +); diff --git a/runtime/js/40_read_file.js b/runtime/js/40_read_file.js index 0ca8f56e90..1efd5338d8 100644 --- a/runtime/js/40_read_file.js +++ b/runtime/js/40_read_file.js @@ -7,32 +7,44 @@ function readFileSync(path) { const file = openSync(path); - const contents = readAllSync(file); - file.close(); - return contents; + try { + const contents = readAllSync(file); + return contents; + } finally { + file.close(); + } } async function readFile(path) { const file = await open(path); - const contents = await readAll(file); - file.close(); - return contents; + try { + const contents = await readAll(file); + return contents; + } finally { + file.close(); + } } function readTextFileSync(path) { const file = openSync(path); - const contents = readAllSync(file); - file.close(); - const decoder = new TextDecoder(); - return decoder.decode(contents); + try { + const contents = readAllSync(file); + const decoder = new TextDecoder(); + return decoder.decode(contents); + } finally { + file.close(); + } } async function readTextFile(path) { const file = await open(path); - const contents = await readAll(file); - file.close(); - const decoder = new TextDecoder(); - return decoder.decode(contents); + try { + const contents = await readAll(file); + const decoder = new TextDecoder(); + return decoder.decode(contents); + } finally { + file.close(); + } } window.__bootstrap.readFile = {