fix: a slow entry in the VFS was blocking the rest
Massimo Melina committed
Nov 25, 2025 at 10:41 UTC
42d49a75635ecf01b79a0d1ac7e502d4976bef00
2 files changed
+8
-7
src/vfs.ts
+7
-6
@@ -319,26 +319,26 @@ export async function* walkNode(parent: VfsNode, {
319
async read() {
320
if (started) return // for simplicity, we care about starting, and never suspend
321
started = true
322
- const { children, source } = parent
322
+ const { source } = parent
323
const taken = prefixPath ? undefined : new Set()
324
const maskApplier = parentMaskApplier(parent)
325
const visitLater: any = []
326
- if (children) for (const child of children) {
326
+ const childrenWorking = parent.children?.length && Promise.all(parent.children.map(async child => {
327
const nodeName = getNodeName(child)
328
const name = prefixPath + nodeName
329
taken?.add(normalizeFilename(name))
330
const item = { ...child, original: child, name, parent }
331
- if (await cantSee(item)) continue
331
+ if (await cantSee(item)) return
332
if (item.source && !item.children?.length) // real items must be accessible, unless there's more to it
333
try { await fs.access(item.source) }
334
- catch { continue }
334
+ catch { return }
335
const isFolder = nodeIsFolder(child)
336
if (onlyFiles ? !isFolder : (!onlyFolders || isFolder))
337
stream.push(item)
338
- if (!depth || !isFolder || cantRecur(item)) continue
338
+ if (!depth || !isFolder || cantRecur(item)) return
339
inheritMasks(item, parent)
340
visitLater.push([item, name]) // prioritize siblings
341
- }
341
+ }))
342
343
try {
344
if (!source)
@@ -382,6 +382,7 @@ export async function* walkNode(parent: VfsNode, {
382
}
383
}
384
finally {
385
+ await childrenWorking
386
for (const [item, name] of visitLater)
387
for await (const x of walkNode(item, { depth: depth - 1, prefixPath: name + '/', ctx, requiredPerm, onlyFolders, parallelizeRecursion }))
388
stream.push(x)
tests/test.ts
+1
-1
@@ -118,7 +118,7 @@ describe('basics', () => {
118
test('inheritNegativeMask', reqList('/tests/page', { outList: ['index.html'] }))
119
120
const zipSize = 13242
121
- const zipOfs = 0x32EF
121
+ const zipOfs = 0x194E
122
const zipLength = 4
123
test('zip.head', req('/f1/?get=zip', { empty:true, length:zipSize }, { method:'HEAD' }) )
124
test('zip.partial', req('/f1/?get=zip', { re:/^page$/, length: zipLength }, { headers: { Range: `bytes=${zipOfs}-${zipOfs+zipLength-1}` } }) )