residual-detach.spec.ts 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738
  1. import { describe, expect, it } from 'vitest'
  2. import { detachResidual } from '../src/index.ts'
  3. describe('detachResidual — fd-3 residual detachment', () => {
  4. it('returns a copy that does NOT share the source frame allocation', () => {
  5. // Simulate the data handler's state: one large joined frame from
  6. // Buffer.concat, sliced past its newline to leave a small residual VIEW.
  7. // The fixture MUST stay larger than Node's Buffer pool threshold
  8. // (`Buffer.poolSize / 2`, 4 KiB): above it `Buffer.from` allocates a
  9. // dedicated backing store whose `byteLength` equals the copy's length,
  10. // which is what the byteLength assertion below pins. A smaller residual
  11. // would be pooled into an 8 KiB shared ArrayBuffer, making `byteLength`
  12. // report 8192 and the assertion false-fail even though the fix is intact.
  13. const joined = Buffer.alloc(1024 * 1024, 0x61) // 1 MiB backing allocation
  14. joined[512] = 0x0a // a newline partway through
  15. const residual = joined.subarray(513) // a view onto `joined`'s backing store
  16. // Before the fix the handler carried this view forward verbatim, pinning the
  17. // whole 1 MiB `joined` allocation behind a residual that reports far fewer
  18. // bytes. A right-sized copy must not point back into `joined`.
  19. const [carried] = detachResidual(residual)
  20. expect(carried).toBeDefined()
  21. expect(carried!.length).toBe(residual.length)
  22. expect(carried!.equals(residual)).toBe(true)
  23. // The core invariant: the copy does NOT share the source frame's backing
  24. // store, so retaining it cannot pin the 1 MiB allocation.
  25. expect(carried!.buffer).not.toBe(joined.buffer)
  26. // And the copy's own backing store is sized to its content — not the whole
  27. // frame. Holds because the fixture exceeds the pool threshold (see above);
  28. // a subarray view would report the source's full byteLength here.
  29. expect(carried!.buffer.byteLength).toBe(carried!.length)
  30. })
  31. it('carries nothing forward for an empty residual', () => {
  32. expect(detachResidual(Buffer.alloc(0))).toEqual([])
  33. })
  34. })