Skip to content

Commit

Permalink
fix(ext/node): add truncate method to the FileHandle class (#27389)
Browse files Browse the repository at this point in the history
  • Loading branch information
filipstev authored Dec 20, 2024
1 parent feb94d0 commit 23f7032
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 20 deletions.
18 changes: 13 additions & 5 deletions ext/node/polyfills/_fs/_fs_ftruncate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,24 @@ export function ftruncate(
: undefined;
const callback: CallbackWithError = typeof lenOrCallback === "function"
? lenOrCallback
: maybeCallback as CallbackWithError;
: (maybeCallback as CallbackWithError);

if (!callback) throw new Error("No callback function supplied");

new FsFile(fd, Symbol.for("Deno.internal.FsFile")).truncate(len).then(
() => callback(null),
callback,
);
new FsFile(fd, Symbol.for("Deno.internal.FsFile"))
.truncate(len)
.then(() => callback(null), callback);
}

export function ftruncateSync(fd: number, len?: number) {
new FsFile(fd, Symbol.for("Deno.internal.FsFile")).truncateSync(len);
}

export function ftruncatePromise(fd: number, len?: number): Promise<void> {
return new Promise((resolve, reject) => {
ftruncate(fd, len, (err) => {
if (err) reject(err);
else resolve();
});
});
}
25 changes: 10 additions & 15 deletions ext/node/polyfills/internal/fs/handle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
ReadOptions,
TextOptionsArgument,
} from "ext:deno_node/_fs/_fs_common.ts";
import { ftruncatePromise } from "ext:deno_node/_fs/_fs_ftruncate.ts";
import { core } from "ext:core/mod.js";

interface WriteResult {
Expand Down Expand Up @@ -73,6 +74,10 @@ export class FileHandle extends EventEmitter {
}
}

truncate(len?: number): Promise<void> {
return fsCall(ftruncatePromise, this, len);
}

readFile(
opt?: TextOptionsArgument | BinaryOptionsArgument | FileOptionsArgument,
): Promise<string | Buffer> {
Expand All @@ -85,11 +90,7 @@ export class FileHandle extends EventEmitter {
length: number,
position: number,
): Promise<WriteResult>;
write(
str: string,
position: number,
encoding: string,
): Promise<WriteResult>;
write(str: string, position: number, encoding: string): Promise<WriteResult>;
write(
bufferOrStr: Uint8Array | string,
offsetOrPosition: number,
Expand Down Expand Up @@ -120,16 +121,10 @@ export class FileHandle extends EventEmitter {
const encoding = lengthOrEncoding;

return new Promise((resolve, reject) => {
write(
this.fd,
str,
position,
encoding,
(err, bytesWritten, buffer) => {
if (err) reject(err);
else resolve({ buffer, bytesWritten });
},
);
write(this.fd, str, position, encoding, (err, bytesWritten, buffer) => {
if (err) reject(err);
else resolve({ buffer, bytesWritten });
});
});
}
}
Expand Down
82 changes: 82 additions & 0 deletions tests/unit_node/_fs/_fs_handle_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,85 @@ Deno.test("[node/fs filehandle.writeFile] Write to file", async function () {

assertEquals(decoder.decode(data), "hello world");
});

Deno.test(
"[node/fs filehandle.truncate] Truncate file with length",
async function () {
const tempFile: string = await Deno.makeTempFile();
const fileHandle = await fs.open(tempFile, "w+");

await fileHandle.writeFile("hello world");

await fileHandle.truncate(5);

const data = Deno.readFileSync(tempFile);
await Deno.remove(tempFile);
await fileHandle.close();

assertEquals(decoder.decode(data), "hello");
},
);

Deno.test(
"[node/fs filehandle.truncate] Truncate file without length",
async function () {
const tempFile: string = await Deno.makeTempFile();
const fileHandle = await fs.open(tempFile, "w+");

await fileHandle.writeFile("hello world");

await fileHandle.truncate();

const data = Deno.readFileSync(tempFile);
await Deno.remove(tempFile);
await fileHandle.close();

assertEquals(decoder.decode(data), "");
},
);

Deno.test(
"[node/fs filehandle.truncate] Truncate file with extension",
async function () {
const tempFile: string = await Deno.makeTempFile();
const fileHandle = await fs.open(tempFile, "w+");

await fileHandle.writeFile("hi");

await fileHandle.truncate(5);

const data = Deno.readFileSync(tempFile);
await Deno.remove(tempFile);
await fileHandle.close();

const expected = new Uint8Array(5);
expected.set(new TextEncoder().encode("hi"));

assertEquals(data, expected);
assertEquals(data.length, 5);
assertEquals(decoder.decode(data.subarray(0, 2)), "hi");
// Verify null bytes
assertEquals(data[2], 0);
assertEquals(data[3], 0);
assertEquals(data[4], 0);
},
);

Deno.test(
"[node/fs filehandle.truncate] Truncate file with negative length",
async function () {
const tempFile: string = await Deno.makeTempFile();
const fileHandle = await fs.open(tempFile, "w+");

await fileHandle.writeFile("hello world");

await fileHandle.truncate(-1);

const data = Deno.readFileSync(tempFile);
await Deno.remove(tempFile);
await fileHandle.close();

assertEquals(decoder.decode(data), "");
assertEquals(data.length, 0);
},
);

0 comments on commit 23f7032

Please sign in to comment.