/
githubmirror
/
deno
Обзор
Документация
Войти
/
githubmirror
/
deno
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
ext/node/polyfills/_fs/_fs_dir.ts
156 строк
4 KB
Bartek Iwańczuk
fix(ext/node): sort fs.readdir entries to match Node.js (#36341)
03 авг 2026, 19:02
Не верифицирован
03 авг 2026, 19:02
9dfa86f
Код
Авторство
О чём код?
// Copyright 2018-2026 the Deno authors. MIT license. import { core, primordials } from "ext:core/mod.js"; import { type Dirent, direntFromDeno, } from "ext:deno_node/internal/fs/utils.mjs"; const { default: assert } = core.loadExtScript("ext:deno_node/assert.ts"); const { ERR_MISSING_ARGS, ERR_DIR_CLOSED } = core.loadExtScript( "ext:deno_node/internal/errors.ts", ); const { TextDecoder } = core.loadExtScript("ext:deno_web/08_text_encoding.js"); const { Promise, ReflectApply, ObjectPrototypeIsPrototypeOf, Uint8ArrayPrototype, PromisePrototypeThen, SymbolAsyncIterator, SymbolAsyncDispose, SymbolDispose, ArrayIteratorPrototypeNext, SymbolIterator, } = primordials; // Note: unlike `fs.readdir`, `fs.opendir`/`Dir` streams entries in filesystem // order and does NOT sort them, matching Node.js (libuv's `uv_fs_readdir`, as // opposed to `uv_fs_scandir` which backs `readdir`). Do not add sorting here. export default class Dir { #dirPath: string | Uint8Array; #syncIterator!: Iterator<Deno.DirEntry, undefined> | null; #asyncIterator!: AsyncIterator<Deno.DirEntry, undefined> | null; #closed = false; constructor(path: string | Uint8Array) { if (!path) { throw new ERR_MISSING_ARGS("path"); } this.#dirPath = path; } get path(): string { if (ObjectPrototypeIsPrototypeOf(Uint8ArrayPrototype, this.#dirPath)) { return new TextDecoder().decode(this.#dirPath); } return this.#dirPath; } // deno-lint-ignore no-explicit-any read(callback?: (...args: any[]) => void): Promise<Dirent | null> { return new Promise((resolve, reject) => { if (this.#closed) { const err = new ERR_DIR_CLOSED(); if (callback) { callback(err); resolve(null); } else { reject(err); } return; } if (!this.#asyncIterator) { this.#asyncIterator = Deno.readDir(this.path)[SymbolAsyncIterator](); } assert(this.#asyncIterator); PromisePrototypeThen( ReflectApply(this.#asyncIterator.next, this.#asyncIterator, []), (iteratorResult) => { resolve( iteratorResult.done ? null : direntFromDeno(iteratorResult.value, this.#dirPath), ); if (callback) { callback( null, iteratorResult.done ? null : direntFromDeno(iteratorResult.value, this.#dirPath), ); } }, (err) => { if (callback) { callback(err); } reject(err); }, ); }); } readSync(): Dirent | null { if (this.#closed) { throw new ERR_DIR_CLOSED(); } if (!this.#syncIterator) { this.#syncIterator = Deno.readDirSync(this.path)![SymbolIterator](); } const iteratorResult = ArrayIteratorPrototypeNext(this.#syncIterator); if (iteratorResult.done) { return null; } else { return direntFromDeno(iteratorResult.value, this.#dirPath); } } /** * Unlike Node, Deno does not require managing resource ids for reading * directories, and therefore does not need to close directories when * finished reading. */ // deno-lint-ignore no-explicit-any close(callback?: (...args: any[]) => void): Promise<void> { return new Promise((resolve) => { this.#closed = true; if (callback) { callback(null); } resolve(); }); } /** * Unlike Node, Deno does not require managing resource ids for reading * directories, and therefore does not need to close directories when * finished reading */ closeSync() { this.#closed = true; } [SymbolDispose]() { this.closeSync(); } [SymbolAsyncDispose](): Promise<void> { return this.close(); } async *[SymbolAsyncIterator](): AsyncIterableIterator<Dirent> { try { while (true) { const dirent: Dirent | null = await this.read(); if (dirent === null) { break; } yield dirent; } } finally { await this.close(); } } }