-
Notifications
You must be signed in to change notification settings - Fork 655
feat(fs/unstable): add open, openSync, and FsFile class #6524
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
712ce5c
docs(fs): update doc checker from merge
jbronder 38fc00d
Merge remote-tracking branch 'upstream/main' into fs_unstable_open
jbronder ea4b370
docs(fs): fix doc checker from merge
jbronder 0c7719e
feat(fs/unstable): add `NodeFsFile` class, `FsFile` type, `util` fns
jbronder bdb0dc6
feat(fs/unstable): add `open(Sync)` API and import references
jbronder a2ccb74
test(fs/unstable): add `NodeFsFile` tests
jbronder 08192f2
test(fs/unstable): add `open(Sync)` tests
jbronder 1f77780
test(fs/unstable): fix `isTerminal` test
jbronder 17932cd
test(fs/unstable): remove `win32` ignore from `isTerminal` test
jbronder df83f66
test(fs/unstable): fix `isTerminal` test
jbronder 11e7e64
test(fs/unstable): fix process import in tests
jbronder a082572
test(fs/unstable): fix process and tty imports for tests
jbronder bf116c1
test(fs/unstable): remove `NodeFsFile` `isTerminal` test
jbronder bdd8c2d
test(fs/unstable): update `FsFile` `utime(Sync)` tests
jbronder 79ccdc7
Merge branch 'main' into fs_unstable_open
kt3k 0e3e437
remove stability notes
kt3k cf77904
store #nodeWriteFd and #nodeReadFd in private fields
kt3k File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,217 @@ | ||
// Copyright 2018-2025 the Deno authors. MIT license. | ||
|
||
import { getNodeFs, getNodeStream, getNodeTty, getNodeUtil } from "./_utils.ts"; | ||
import { mapError } from "./_map_error.ts"; | ||
import type { FileInfo, FsFile, SetRawOptions } from "./unstable_types.ts"; | ||
import { toFileInfo } from "./_to_file_info.ts"; | ||
|
||
/** | ||
* The internal class to convert a Node file descriptor into a FsFile object. | ||
*/ | ||
export class NodeFsFile implements FsFile { | ||
#nodeFs = getNodeFs(); | ||
#nodeStream = getNodeStream(); | ||
#nodeTty = getNodeTty(); | ||
#nodeUtil = getNodeUtil(); | ||
#nodeReadFd = this.#nodeUtil.promisify(this.#nodeFs.read); | ||
#nodeWriteFd = this.#nodeUtil.promisify(this.#nodeFs.write); | ||
|
||
#closed: boolean; | ||
#rid: number; | ||
#readableStream?: ReadableStream<Uint8Array>; | ||
#writableStream?: WritableStream<Uint8Array>; | ||
|
||
constructor(fd: number) { | ||
this.#rid = fd; | ||
this.#closed = false; | ||
} | ||
|
||
get readable(): ReadableStream<Uint8Array> { | ||
if (this.#readableStream == null) { | ||
const readStream = this.#nodeFs.createReadStream(null as unknown, { | ||
fd: this.#rid, | ||
autoClose: false, | ||
}); | ||
this.#readableStream = this.#nodeStream.Readable.toWeb(readStream); | ||
} | ||
return this.#readableStream as ReadableStream; | ||
} | ||
|
||
get writable(): WritableStream<Uint8Array> { | ||
if (this.#writableStream == null) { | ||
const writeStream = this.#nodeFs.createWriteStream(null as unknown, { | ||
fd: this.#rid, | ||
autoClose: false, | ||
}); | ||
this.#writableStream = this.#nodeStream.Writable.toWeb(writeStream); | ||
} | ||
return this.#writableStream as WritableStream; | ||
} | ||
|
||
[Symbol.dispose](): void { | ||
if (!this.#closed) { | ||
this.close(); | ||
} | ||
} | ||
|
||
close(): void { | ||
this.#closed = true; | ||
this.#nodeFs.closeSync(this.#rid); | ||
} | ||
|
||
isTerminal(): boolean { | ||
return this.#nodeTty.isatty(this.#rid); | ||
} | ||
|
||
// deno-lint-ignore require-await no-unused-vars | ||
async lock(exclusive?: boolean): Promise<void> { | ||
throw new Error("Method not implemented."); | ||
} | ||
|
||
// deno-lint-ignore no-unused-vars | ||
lockSync(exclusive?: boolean): void { | ||
throw new Error("Method not implemented."); | ||
} | ||
|
||
async read(p: Uint8Array): Promise<number | null> { | ||
try { | ||
const { bytesRead } = await this.#nodeReadFd( | ||
this.#rid, | ||
p, | ||
0, | ||
p.length, | ||
null, | ||
); | ||
return bytesRead === 0 ? null : bytesRead; | ||
} catch (error) { | ||
throw mapError(error); | ||
} | ||
} | ||
|
||
readSync(p: Uint8Array): number | null { | ||
try { | ||
const bytesRead = this.#nodeFs.readSync(this.#rid, p); | ||
return bytesRead === 0 ? null : bytesRead; | ||
} catch (error) { | ||
throw mapError(error); | ||
} | ||
} | ||
|
||
//deno-lint-ignore no-unused-vars | ||
setRaw(mode: boolean, options?: SetRawOptions): void { | ||
throw new Error("Method not implemented."); | ||
} | ||
|
||
async stat(): Promise<FileInfo> { | ||
const nodeStatFd = this.#nodeUtil.promisify(this.#nodeFs.fstat); | ||
try { | ||
const fdStat = await nodeStatFd(this.#rid); | ||
return toFileInfo(fdStat); | ||
} catch (error) { | ||
throw mapError(error); | ||
} | ||
} | ||
|
||
statSync(): FileInfo { | ||
try { | ||
const fdStat = this.#nodeFs.fstatSync(this.#rid); | ||
return toFileInfo(fdStat); | ||
} catch (error) { | ||
throw mapError(error); | ||
} | ||
} | ||
|
||
async sync(): Promise<void> { | ||
const nodeFsyncFd = this.#nodeUtil.promisify(this.#nodeFs.fsync); | ||
try { | ||
await nodeFsyncFd(this.#rid); | ||
} catch (error) { | ||
throw mapError(error); | ||
} | ||
} | ||
|
||
syncSync(): void { | ||
try { | ||
this.#nodeFs.fsyncSync(this.#rid); | ||
} catch (error) { | ||
throw mapError(error); | ||
} | ||
} | ||
|
||
async syncData(): Promise<void> { | ||
const nodeFdatasyncFd = this.#nodeUtil.promisify(this.#nodeFs.fdatasync); | ||
try { | ||
await nodeFdatasyncFd(this.#rid); | ||
} catch (error) { | ||
throw mapError(error); | ||
} | ||
} | ||
|
||
syncDataSync(): void { | ||
try { | ||
this.#nodeFs.fdatasyncSync(this.#rid); | ||
} catch (error) { | ||
throw mapError(error); | ||
} | ||
} | ||
|
||
async truncate(len?: number): Promise<void> { | ||
const nodeTruncateFd = this.#nodeUtil.promisify(this.#nodeFs.ftruncate); | ||
try { | ||
await nodeTruncateFd(this.#rid, len); | ||
} catch (error) { | ||
throw mapError(error); | ||
} | ||
} | ||
|
||
truncateSync(len?: number): void { | ||
try { | ||
this.#nodeFs.ftruncateSync(this.#rid, len); | ||
} catch (error) { | ||
throw mapError(error); | ||
} | ||
} | ||
|
||
// deno-lint-ignore require-await | ||
async unlock(): Promise<void> { | ||
throw new Error("Method not implemented."); | ||
} | ||
|
||
unlockSync(): void { | ||
throw new Error("Method not implemented."); | ||
} | ||
|
||
async utime(atime: number | Date, mtime: number | Date): Promise<void> { | ||
const nodeUtimeFd = this.#nodeUtil.promisify(this.#nodeFs.futimes); | ||
try { | ||
await nodeUtimeFd(this.#rid, atime, mtime); | ||
} catch (error) { | ||
throw mapError(error); | ||
} | ||
} | ||
|
||
utimeSync(atime: number | Date, mtime: number | Date): void { | ||
try { | ||
this.#nodeFs.futimesSync(this.#rid, atime, mtime); | ||
} catch (error) { | ||
throw mapError(error); | ||
} | ||
} | ||
|
||
async write(p: Uint8Array): Promise<number> { | ||
try { | ||
const { bytesWritten } = await this.#nodeWriteFd(this.#rid, p); | ||
return bytesWritten; | ||
} catch (error) { | ||
throw mapError(error); | ||
} | ||
} | ||
|
||
writeSync(p: Uint8Array): number { | ||
try { | ||
return this.#nodeFs.writeSync(this.#rid, p); | ||
} catch (error) { | ||
throw mapError(error); | ||
} | ||
} | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks reasonable. Nice