Skip to content

Commit 8cda4cf

Browse files
authored
feat(node/fs): Add a chmod method to the FileHandle class (#27522)
Add the chmod method to the FileHandle class in node compat as part of #25554
1 parent b7fb5a5 commit 8cda4cf

File tree

3 files changed

+34
-5
lines changed

3 files changed

+34
-5
lines changed

ext/node/polyfills/_fs/_fs_open.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ export function openPromise(
153153
return new Promise((resolve, reject) => {
154154
open(path, flags, mode, (err, fd) => {
155155
if (err) reject(err);
156-
else resolve(new FileHandle(fd));
156+
else resolve(new FileHandle(fd, path));
157157
});
158158
});
159159
}

ext/node/polyfills/internal/fs/handle.ts

+15-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import { EventEmitter } from "node:events";
77
import { Buffer } from "node:buffer";
8-
import { promises, read, write } from "node:fs";
8+
import { Mode, promises, read, write } from "node:fs";
99
export type { BigIntStats, Stats } from "ext:deno_node/_fs/_fs_stat.ts";
1010
import {
1111
BinaryOptionsArgument,
@@ -26,11 +26,15 @@ interface ReadResult {
2626
buffer: Buffer;
2727
}
2828

29+
type Path = string | Buffer | URL;
2930
export class FileHandle extends EventEmitter {
3031
#rid: number;
31-
constructor(rid: number) {
32+
#path: Path;
33+
34+
constructor(rid: number, path: Path) {
3235
super();
3336
this.#rid = rid;
37+
this.#path = path;
3438
}
3539

3640
get fd() {
@@ -144,17 +148,24 @@ export class FileHandle extends EventEmitter {
144148
stat(options?: { bigint: boolean }): Promise<Stats | BigIntStats> {
145149
return fsCall(promises.fstat, this, options);
146150
}
151+
chmod(mode: Mode): Promise<void> {
152+
assertNotClosed(this, promises.chmod.name);
153+
return promises.chmod(this.#path, mode);
154+
}
147155
}
148156

149-
function fsCall(fn, handle, ...args) {
157+
function assertNotClosed(handle: FileHandle, syscall: string) {
150158
if (handle.fd === -1) {
151159
const err = new Error("file closed");
152160
throw Object.assign(err, {
153161
code: "EBADF",
154-
syscall: fn.name,
162+
syscall,
155163
});
156164
}
165+
}
157166

167+
function fsCall(fn, handle, ...args) {
168+
assertNotClosed(handle, fn.name);
158169
return fn(handle.fd, ...args);
159170
}
160171

tests/unit_node/_fs/_fs_handle_test.ts

+18
Original file line numberDiff line numberDiff line change
@@ -199,3 +199,21 @@ Deno.test(
199199
assertEquals(data.length, 0);
200200
},
201201
);
202+
203+
Deno.test({
204+
name: "[node/fs filehandle.chmod] Change the permissions of the file",
205+
ignore: Deno.build.os === "windows",
206+
async fn() {
207+
const fileHandle = await fs.open(testData);
208+
209+
const readOnly = 0o444;
210+
await fileHandle.chmod(readOnly.toString(8));
211+
assertEquals(Deno.statSync(testData).mode! & 0o777, readOnly);
212+
213+
const readWrite = 0o666;
214+
await fileHandle.chmod(readWrite.toString(8));
215+
assertEquals(Deno.statSync(testData).mode! & 0o777, readWrite);
216+
217+
await fileHandle.close();
218+
},
219+
});

0 commit comments

Comments
 (0)