Skip to content

🍕 Fix buffer dependency stub#253

Merged
jjpaulino merged 1 commit into
masterfrom
jordan/fix-buffer-stub
Jul 2, 2026
Merged

🍕 Fix buffer dependency stub#253
jjpaulino merged 1 commit into
masterfrom
jordan/fix-buffer-stub

Conversation

@jjpaulino

@jjpaulino jjpaulino commented Jul 2, 2026

Copy link
Copy Markdown
Member

What does this PR do?

Hardens the Vite buffer browser-compat stub so third-party libraries that subclass Buffer no longer crash the kiln-edit bundle at module-evaluation time.

The stub's fallback (used when the page has no global Buffer polyfill) was a plain object. Any dependency doing SafeBuffer.prototype = Object.create(Buffer.prototype) therefore hit Object.create(undefined) and threw — before Kiln could boot:

Uncaught TypeError: Object prototype may only be an Object or null: undefined
    at Object.create (<anonymous>)
    at vite-kiln-edit-init-…js

No linked issue — surfaced during the Vite kiln-edit rollout (context below).

Why are we doing this? Any context or related work?

Downstream in nymag/sites, edit mode began crashing the moment a component pulled crypto-browserify into the kiln bundle. Its transitive stack (create-hash, create-hmac, sha.js, cipher-base, …) depends on safe-buffer@5.2.1, whose module init runs SafeBuffer.prototype = Object.create(Buffer.prototype).

safe-buffer feature-detects from / alloc / allocUnsafe / allocUnsafeSlow; when all four exist it just re-exports the provided buffer module and skips subclassing. The old stub was missing allocUnsafe / allocUnsafeSlow and had no prototype (it was a plain object), so it fell into the subclassing branch and blew up.

The rewrite makes the fallback:

  • a function with a real .prototype (subclass-safe),
  • expose the full from / alloc / allocUnsafe / allocUnsafeSlow / concat surface, so safe-buffer takes the cheap re-export path, and
  • add SlowBuffer for API parity.

A real globalThis.Buffer polyfill is still preferred when the page provides one.

Where should a reviewer start?

  • The fixBUFFER_STUB in browser-compat.js: function-shaped Buffer + full alloc API + SlowBuffer. The block comment documents the two constraints (real prototype; expose all four alloc methods).
  • Testsbuffer specs plus the evalEsmStub sandbox helper: full alloc API present, fallback is subclass-safe when there is no global Buffer, and a real global Buffer is preferred when present.
Manual testing steps?
  1. In a consuming app whose kiln bundle imports a crypto lib (crypto-browserifysafe-buffer), build JS: npx clay vite --only js.
  2. Open a page in edit mode.
  3. Before: Uncaught TypeError: Object prototype may only be an Object or null: undefined. After: edit mode boots normally.

Unit tests: npx jest lib/cmd/vite/plugins/browser-compat.test.js (green on Node 18 / 20 / 22 in CI).

Screenshots

N/A — console error on boot → clean boot.

Additional Context

Same failure family as the other Node-builtin stubs the Vite rollout has surfaced one at a time — each edit-mode code path that reaches a different builtin exposes the next incomplete stub. This change makes the buffer fallback robust for any Buffer.prototype subclasser, not just safe-buffer.

@jjpaulino jjpaulino self-assigned this Jul 2, 2026
@jjpaulino jjpaulino merged commit 0105d82 into master Jul 2, 2026
6 checks passed
@coveralls

Copy link
Copy Markdown

Coverage Status

coverage: 87.084%. remained the same — jordan/fix-buffer-stub into master

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants