Skip to content

Commit ba73f5e

Browse files
committed
chore: track fs state on WriteEntry class, not in arguments
1 parent bf69383 commit ba73f5e

File tree

1 file changed

+62
-38
lines changed

1 file changed

+62
-38
lines changed

lib/write-entry.js

+62-38
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,15 @@ const WriteEntry = warner(class WriteEntry extends MiniPass {
4949
this.noMtime = !!opt.noMtime
5050
this.mtime = opt.mtime || null
5151

52+
this.fd = null
53+
this.blockLen = null
54+
this.blockRemain = null
55+
this.buf = null
56+
this.offset = null
57+
this.length = null
58+
this.pos = null
59+
this.remain = null
60+
5261
if (typeof opt.onwarn === 'function')
5362
this.on('warn', opt.onwarn)
5463

@@ -214,74 +223,88 @@ const WriteEntry = warner(class WriteEntry extends MiniPass {
214223
}
215224

216225
[ONOPENFILE] (fd) {
217-
const blockLen = 512 * Math.ceil(this.stat.size / 512)
218-
const bufLen = Math.min(blockLen, this.maxReadSize)
219-
const buf = Buffer.allocUnsafe(bufLen)
220-
this[READ](fd, buf, 0, buf.length, 0, this.stat.size, blockLen)
226+
this.fd = fd
227+
this.blockLen = 512 * Math.ceil(this.stat.size / 512)
228+
this.blockRemain = this.blockLen
229+
const bufLen = Math.min(this.blockLen, this.maxReadSize)
230+
this.buf = Buffer.allocUnsafe(bufLen)
231+
this.offset = 0
232+
this.pos = 0
233+
this.remain = this.stat.size
234+
this.length = this.buf.length
235+
this[READ](this.stat.size)
221236
}
222237

223-
[READ] (fd, buf, offset, length, pos, remain, blockRemain) {
238+
[READ] () {
239+
const { fd, buf, offset, length, pos } = this
224240
fs.read(fd, buf, offset, length, pos, (er, bytesRead) => {
225241
if (er) {
226242
// ignoring the error from close(2) is a bad practice, but at
227243
// this point we already have an error, don't need another one
228-
return this[CLOSE](fd, () => this.emit('error', er))
244+
return this[CLOSE](() => this.emit('error', er))
229245
}
230-
this[ONREAD](fd, buf, offset, length, pos, remain, blockRemain, bytesRead)
246+
this[ONREAD](bytesRead)
231247
})
232248
}
233249

234-
[CLOSE] (fd, cb) {
235-
fs.close(fd, cb)
250+
[CLOSE] (cb) {
251+
fs.close(this.fd, cb)
236252
}
237253

238-
[ONREAD] (fd, buf, offset, length, pos, remain, blockRemain, bytesRead) {
239-
if (bytesRead <= 0 && remain > 0) {
254+
[ONREAD] (bytesRead) {
255+
if (bytesRead <= 0 && this.remain > 0) {
240256
const er = new Error('encountered unexpected EOF')
241257
er.path = this.absolute
242258
er.syscall = 'read'
243259
er.code = 'EOF'
244-
return this[CLOSE](fd, () => this.emit('error', er))
260+
return this[CLOSE](() => this.emit('error', er))
245261
}
246262

247-
if (bytesRead > remain) {
263+
if (bytesRead > this.remain) {
248264
const er = new Error('did not encounter expected EOF')
249265
er.path = this.absolute
250266
er.syscall = 'read'
251267
er.code = 'EOF'
252-
return this[CLOSE](fd, () => this.emit('error', er))
268+
return this[CLOSE](() => this.emit('error', er))
253269
}
254270

255271
// null out the rest of the buffer, if we could fit the block padding
256-
if (bytesRead === remain) {
257-
for (let i = bytesRead; i < length && bytesRead < blockRemain; i++) {
258-
buf[i + offset] = 0
272+
// at the end of this loop, we've incremented bytesRead and this.remain
273+
// to be incremented up to the blockRemain level, as if we had expected
274+
// to get a null-padded file, and read it until the end. then we will
275+
// decrement both remain and blockRemain by bytesRead, and know that we
276+
// reached the expected EOF, without any null buffer to append.
277+
if (bytesRead === this.remain) {
278+
for (let i = bytesRead; i < this.length && bytesRead < this.blockRemain; i++) {
279+
this.buf[i + this.offset] = 0
259280
bytesRead++
260-
remain++
281+
this.remain++
261282
}
262283
}
263284

264-
const writeBuf = offset === 0 && bytesRead === buf.length ?
265-
buf : buf.slice(offset, offset + bytesRead)
266-
remain -= bytesRead
267-
blockRemain -= bytesRead
268-
pos += bytesRead
269-
offset += bytesRead
285+
const writeBuf = this.offset === 0 && bytesRead === this.buf.length ?
286+
this.buf : this.buf.slice(this.offset, this.offset + bytesRead)
287+
this.remain -= bytesRead
288+
this.blockRemain -= bytesRead
289+
this.pos += bytesRead
290+
this.offset += bytesRead
270291

271292
this.write(writeBuf)
272293

273-
if (!remain) {
274-
if (blockRemain)
275-
this.write(Buffer.alloc(blockRemain))
276-
return this[CLOSE](fd, er => er ? this.emit('error', er) : this.end())
294+
if (!this.remain) {
295+
if (this.blockRemain)
296+
this.write(Buffer.alloc(this.blockRemain))
297+
return this[CLOSE](er => er ? this.emit('error', er) : this.end())
277298
}
278299

279-
if (offset >= length) {
280-
buf = Buffer.allocUnsafe(length)
281-
offset = 0
300+
if (this.offset >= this.length) {
301+
// if we only have a smaller bit left to read, alloc a smaller buffer
302+
// otherwise, keep it the same length it was before.
303+
this.buf = Buffer.allocUnsafe(Math.min(this.blockRemain, this.buf.length))
304+
this.offset = 0
282305
}
283-
length = buf.length - offset
284-
this[READ](fd, buf, offset, length, pos, remain, blockRemain)
306+
this.length = this.buf.length - this.offset
307+
this[READ]()
285308
}
286309
})
287310

@@ -298,25 +321,26 @@ class WriteEntrySync extends WriteEntry {
298321
this[ONOPENFILE](fs.openSync(this.absolute, 'r'))
299322
}
300323

301-
[READ] (fd, buf, offset, length, pos, remain, blockRemain) {
324+
[READ] () {
302325
let threw = true
303326
try {
327+
const { fd, buf, offset, length, pos } = this
304328
const bytesRead = fs.readSync(fd, buf, offset, length, pos)
305-
this[ONREAD](fd, buf, offset, length, pos, remain, blockRemain, bytesRead)
329+
this[ONREAD](bytesRead)
306330
threw = false
307331
} finally {
308332
// ignoring the error from close(2) is a bad practice, but at
309333
// this point we already have an error, don't need another one
310334
if (threw) {
311335
try {
312-
this[CLOSE](fd, () => {})
336+
this[CLOSE](() => {})
313337
} catch (er) {}
314338
}
315339
}
316340
}
317341

318-
[CLOSE] (fd, cb) {
319-
fs.closeSync(fd)
342+
[CLOSE] (cb) {
343+
fs.closeSync(this.fd)
320344
cb()
321345
}
322346
}

0 commit comments

Comments
 (0)