2 Commits
Author SHA1 Message Date
sugoidogo bbd975feb6 remove close/abort override
Release / release (push) Successful in 23s
2026-02-15 20:22:23 -08:00
sugoidogo 1bd153de5b use single fd for all operations 2026-02-15 19:57:19 -08:00
2 changed files with 26 additions and 21 deletions
+9 -6
View File
@@ -1,14 +1,17 @@
import NodeFileSystemDirectoryHandle from '../dist/NodeFileSystemDirectoryHandle.js'
import NodeFileSystemDirectoryHandle from '../src/NodeFileSystemDirectoryHandle.ts'
const textText="Hello World!"
const cwd_directory_handle = new NodeFileSystemDirectoryHandle('.')
const test_directory_handle = await cwd_directory_handle.getDirectoryHandle('test', { 'create': true })
const file_handle = await test_directory_handle.getFileHandle('test.txt', { 'create': true })
for (let i = 0; i < 10000; i++) {
const file_handle = await test_directory_handle.getFileHandle(i+'.txt', { 'create': true })
const writable = await file_handle.createWritable()
writable.write('Hello World!')
writable.close()
await writable.write('Hello World!')
await writable.close()
const file = await file_handle.getFile()
console.log(file.type)
console.log(await file.text())
const text = await file.text()
if(text!==textText) throw new Error("failed to read back written data")
}
const result = await cwd_directory_handle.getFileHandle('test/test.txt').catch(error => 'blocked path traversal')
if (typeof result === 'string') console.log(result)
else console.error('path traversal not blocked')
+13 -11
View File
@@ -1,5 +1,4 @@
import * as fs from 'node:fs'
import * as asyncfs from 'node:fs/promises'
import * as path from 'node:path'
import { Writable } from 'node:stream'
import type {
@@ -11,35 +10,38 @@ import type {
export default class NodeFileSystemWritableFileStream extends WritableStream implements FileSystemWritableFileStream {
#seek_position = 0
#name: string
#fd: number
constructor(name: string, options: FileSystemCreateWritableOptions = {}) {
name = path.normalize(name)
super(Writable.toWeb(fs.createWriteStream(name)))
this.#name = name
if(!options.keepExistingData) this.truncate(0)
let flags = 'w'
if (!options.keepExistingData) flags = 'r+'
const fd = fs.openSync(name, flags)
super(Writable.toWeb(fs.createWriteStream(name, { "fd": fd })))
this.#fd = fd
}
async seek(position: number): Promise<void> {
if (this.locked) throw new Error("stream is locked")
this.#seek_position = position
}
truncate(size: number): Promise<void> {
return asyncfs.truncate(this.#name, size)
async truncate(size: number): Promise<void> {
if (this.locked) throw new Error("stream is locked")
return fs.ftruncateSync(this.#fd, size)
}
async write(wdata: FileSystemWriteChunkType): Promise<void> {
if (this.locked) throw new Error("stream is locked")
if (wdata instanceof Blob) wdata = await wdata.bytes()
if (typeof wdata === 'string') wdata = new TextEncoder().encode(wdata)
let wsize: number = null
let pseek_position = this.#seek_position
if ((wdata as WriteParams).type) {
const { type, position, size, data } = (wdata as WriteParams)
if (type === 'truncate') return asyncfs.truncate(this.#name, size)
if (type === 'truncate') return this.truncate(size)
if (position) this.#seek_position = position
if (type === 'seek') return
if (size) wsize = size
wdata = data
}
const file = await asyncfs.open(this.#name,'r+')
await file.write((wdata as Uint8Array), null, wsize, this.#seek_position)
await file.close()
fs.writeSync(this.#fd, (wdata as Uint8Array), null, wsize, this.#seek_position)
this.#seek_position = pseek_position
}
}