fix(01-08): B+ — vite-plugin-node-polyfills for Buffer (resolves runtime ts-ebml crash)

Layer 2 of the extended SW-bundle-import gate caught a runtime
ReferenceError: Buffer is not defined at EBMLDecoder.constructor
(this._buffer = Buffer.alloc(0)). Reached from remuxSegments via
extractFramesFromSegment for every input segment — would crash
the SW on every SAVE_ARCHIVE click in real Chrome.

ts-ebml has a 5-year-old open issue (legokichi/ts-ebml#37,
"Can't use Buffer in browser") acknowledging the incompatibility
with no maintainer fix. The canonical Vite workaround is
vite-plugin-node-polyfills with a narrow Buffer-only config (per
the plugin author's official docs).

Changes:
- vite-plugin-node-polyfills@0.27.0 added as devDependency
- vite.config.ts adds nodePolyfills plugin with narrow config:
  include: ['buffer'], globals.Buffer: true, globals.global: false,
  globals.process: false, protocolImports: false (Buffer only, no
  stdlib pull-in)
- bundle delta: SW chunk 373.05 kB (-0.49 kB vs C-config alone);
  +27.48 kB shared polyfill chunk (index-CgqXENQe.js, used by SW
  and offscreen). Net cost ~26.3 kB for full Buffer support.

Bundle verification:
- bundled EBMLDecoder.js now reads `this._buffer = me.alloc(0)`
  where `me` is the imported polyfill Buffer (was `Buffer.alloc(0)`
  against undefined globalThis.Buffer). Same rewrite applied to
  all 3 Buffer.alloc/Buffer.concat/Buffer.from sites in ts-ebml.
- bundle does NOT depend on globalThis.Buffer (the polyfill
  rewrites references as imports, not as global assignments) —
  Layer 1 of the gate still strips Buffer from globalThis and
  passes, confirming this.

Layer 2 gate: RED → GREEN. resolve.alias.ebml fix from commit
52c7636 preserved — still required for ebml CJS-interop;
the polyfill addresses an orthogonal runtime concern.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-17 12:17:50 +02:00
parent cc6e81a825
commit dd7bf00d1d
3 changed files with 1952 additions and 0 deletions

1941
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -20,6 +20,7 @@
"@types/chrome": "^0.0.268", "@types/chrome": "^0.0.268",
"typescript": "^5.5.4", "typescript": "^5.5.4",
"vite": "^5.4.2", "vite": "^5.4.2",
"vite-plugin-node-polyfills": "^0.27.0",
"vitest": "^4" "vitest": "^4"
} }
} }

View File

@@ -1,5 +1,6 @@
import { defineConfig } from 'vite'; import { defineConfig } from 'vite';
import { crx } from '@crxjs/vite-plugin'; import { crx } from '@crxjs/vite-plugin';
import { nodePolyfills } from 'vite-plugin-node-polyfills';
import manifest from './manifest.json'; import manifest from './manifest.json';
export default defineConfig({ export default defineConfig({
@@ -10,6 +11,15 @@ export default defineConfig({
injectCss: false, injectCss: false,
}, },
}), }),
nodePolyfills({
include: ['buffer'],
globals: {
Buffer: true,
global: false,
process: false,
},
protocolImports: false,
}),
], ],
resolve: { resolve: {
alias: { alias: {