mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-03 04:38:33 +00:00
* fix(cli): bump @puppeteer/browsers to ^3.0.6 to fix render hang on node >=24.16 `hyperframes render` (and `browser ensure --force`) hangs forever during Chrome provisioning on Node >= 24.16 (repro'd on macOS arm64 / Node 26.5.0; fine on Node 22). Root cause is a transitive extractor bug, not our logic: @puppeteer/browsers@2.13.x install() -> extract-zip@2.0.1 -> yauzl@2.10.0 A classic-stream backpressure regression (nodejs/node#63487, works 24.15, breaks 24.16+) surfaces a latent fd-slicer destroy() bug in yauzl 2.x (yauzl#169). The inflate read stream stalls partway through the first entry large enough to cross the write highWaterMark (chrome-headless-shell's 1.86MB LICENSE.headless_shell, stalls at ~1.31MB), never emits `end`, so stream.pipeline never settles and extraction busy-spins. The half-extracted cache has no executable, so every later render re-enters "Cached binary missing -> re-download" and hangs again (puppeteer#14957). Fix: @puppeteer/browsers 3.0.2 dropped extract-zip/yauzl entirely (now uses modern-tar). Verified 3.0.6 extracts chrome-headless-shell cleanly under Node 26.5.0 and keeps the full API manager.ts uses (install, getInstalledBrowsers, Cache, computeExecutablePath, detectBrowserPlatform, Browser) with an identical on-disk cache layout. Cross-platform (the same .zip/yauzl path affected Linux + Windows too). Adds a regression guard asserting the pin stays on the extractor-free major (>= 3) and never reintroduces extract-zip/yauzl. Fixes #2103 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore(cli): clarify extractor-guard wording — yauzl is an optional peer, not dropped entirely Review note on #2104: @puppeteer/browsers 3.0.6 keeps yauzl as an optional peer fallback (default extractor is modern-tar), so the regression-guard comment + it-text shouldn't say it was 'dropped entirely'. Test assertions (extract-zip + yauzl absent from `dependencies`) unchanged and correct. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
bdb9a34e1c
commit
ccab6207c4
@@ -28,7 +28,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@hono/node-server": "^1.8.0",
|
||||
"@puppeteer/browsers": "^2.13.0",
|
||||
"@puppeteer/browsers": "^3.0.6",
|
||||
"adm-zip": "^0.5.16",
|
||||
"citty": "^0.2.1",
|
||||
"compare-versions": "^6.1.1",
|
||||
|
||||
@@ -599,3 +599,39 @@ describe("installWithCorruptArchiveRecovery", () => {
|
||||
expect(clearCache).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
// Regression guard for HF#2103: `hyperframes render` hung forever on macOS
|
||||
// (Apple Silicon) under Node >= 24.16. Root cause was NOT in this file — it was
|
||||
// the extractor `@puppeteer/browsers` <3.0.2 shells out to. That chain
|
||||
// (`@puppeteer/browsers` -> `extract-zip@2.0.1` -> `yauzl@2.10.0`) hits a
|
||||
// classic-stream backpressure regression (nodejs/node#63487) that surfaces a
|
||||
// latent fd-slicer `destroy()` bug in yauzl 2.x (yauzl#169): the inflate read
|
||||
// stream stalls partway through the first entry large enough to cross the write
|
||||
// highWaterMark, never emits `end`, and `stream.pipeline` never settles — so
|
||||
// extraction busy-spins forever, leaving a half-extracted cache with no
|
||||
// executable (puppeteer/puppeteer#14957).
|
||||
//
|
||||
// `@puppeteer/browsers` 3.0.2 dropped `extract-zip` as a dependency and now
|
||||
// extracts with `modern-tar` by default (`yauzl` lingers only as an optional
|
||||
// peer fallback — no longer a runtime dependency), which is the fix. This test
|
||||
// fails if a dependency change ever drags the pin back below 3.x — i.e.
|
||||
// reintroduces the broken extractor as a hard dependency.
|
||||
describe("@puppeteer/browsers pin (HF#2103 extractor-hang regression guard)", () => {
|
||||
it("stays on the major (>= 3) that dropped extract-zip and no longer depends on yauzl", async () => {
|
||||
const { createRequire } = await import("node:module");
|
||||
const require = createRequire(import.meta.url);
|
||||
const pkg = require("@puppeteer/browsers/package.json") as {
|
||||
version: string;
|
||||
dependencies?: Record<string, string>;
|
||||
};
|
||||
|
||||
const major = Number.parseInt(pkg.version.split(".")[0] ?? "0", 10);
|
||||
expect(major).toBeGreaterThanOrEqual(3);
|
||||
|
||||
// Belt and suspenders: the durable fix is the *absence* of the broken
|
||||
// extractor, not just a version number, so assert it directly.
|
||||
const deps = pkg.dependencies ?? {};
|
||||
expect(deps["extract-zip"]).toBeUndefined();
|
||||
expect(deps["yauzl"]).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user