mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-03 04:38:33 +00:00
fix(cli): page closures survive keepNames transpilation; format motion-blur
Running the CLI from source (tsx dev script, as CI's smoke job does) transpiles with keepNames, which rewrites named inner functions in serialized page closures into __name(...) calls — a helper that exists in the Node bundle but not in the browser realm. The unified seek closure was the first validate-path page function with named inner functions, so 'hyperframes validate' threw '__name is not defined' in CI while the dist build worked. Every session opener now installs a no-op __name shim via evaluateOnNewDocument before any page script runs, immunizing all serialized closures regardless of build mode.
This commit is contained in:
@@ -339,3 +339,21 @@ describe("runFfmpegOnce", () => {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("installPageFunctionGuard", () => {
|
||||
it("defines the keepNames __name shim in the page before any script runs", async () => {
|
||||
const evaluateOnNewDocument = vi.fn(async () => undefined);
|
||||
|
||||
await installPageFunctionGuard({ evaluateOnNewDocument });
|
||||
|
||||
expect(evaluateOnNewDocument).toHaveBeenCalledOnce();
|
||||
const source = evaluateOnNewDocument.mock.calls[0]?.[0] as string;
|
||||
expect(source).toContain("self.__name");
|
||||
// The shim must be a no-op passthrough so wrapped functions stay callable.
|
||||
const shim = new Function(`const self = {}; ${source}; return self.__name;`)() as (
|
||||
fn: unknown,
|
||||
) => unknown;
|
||||
const marker = () => 42;
|
||||
expect(shim(marker)).toBe(marker);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -131,6 +131,19 @@ async function waitForCompositionSettle(
|
||||
return runtimeReady;
|
||||
}
|
||||
|
||||
// tsx/esbuild-style dev transpilers run with keepNames, which rewrites named
|
||||
// inner functions in serialized page closures into __name(...) calls — a
|
||||
// helper that exists in the Node bundle but not in the browser realm, so any
|
||||
// page.evaluate/waitForFunction whose closure defines a named function throws
|
||||
// "__name is not defined" when the CLI runs from source. Defining a no-op in
|
||||
// the page before any script runs immunizes every serialized closure, current
|
||||
// and future, regardless of how the CLI was built.
|
||||
export async function installPageFunctionGuard(page: {
|
||||
evaluateOnNewDocument(source: string): Promise<unknown>;
|
||||
}): Promise<void> {
|
||||
await page.evaluateOnNewDocument("self.__name = self.__name || ((fn) => fn);");
|
||||
}
|
||||
|
||||
export async function openSettledCompositionPage(
|
||||
html: string,
|
||||
url: string,
|
||||
@@ -154,6 +167,7 @@ export async function openSettledCompositionPage(
|
||||
});
|
||||
|
||||
const page = await chromeBrowser.newPage();
|
||||
await installPageFunctionGuard(page);
|
||||
await page.setViewport(viewport);
|
||||
await options.beforeNavigate?.(page);
|
||||
await page.goto(url, { waitUntil: "domcontentloaded", timeout: 10000 });
|
||||
|
||||
@@ -28,6 +28,7 @@ import {
|
||||
import { findMotionSpec, readMotionSpec, type MotionSpec } from "../utils/motionSpec.js";
|
||||
import {
|
||||
AUDIT_SEEK_OPTIONS,
|
||||
installPageFunctionGuard,
|
||||
seekCompositionTimeline,
|
||||
waitForCompositionFonts,
|
||||
type SeekCompositionTimelineOptions,
|
||||
@@ -214,6 +215,7 @@ async function runLayoutAudit(
|
||||
});
|
||||
|
||||
const page = await chromeBrowser.newPage();
|
||||
await installPageFunctionGuard(page);
|
||||
await page.setViewport({ width: 1920, height: 1080 });
|
||||
await page.goto(server.url, { waitUntil: "domcontentloaded", timeout: 10000 });
|
||||
await alignViewportToComposition(page, server.url);
|
||||
|
||||
@@ -15,6 +15,7 @@ import { resolveCompositionViewportFromHtml } from "../utils/compositionViewport
|
||||
import { c } from "../ui/colors.js";
|
||||
import { printDeprecationNotice, withMeta } from "../utils/updateCheck.js";
|
||||
import {
|
||||
installPageFunctionGuard,
|
||||
resolveCliChromeGpuMode,
|
||||
seekCompositionTimeline,
|
||||
} from "../capture/captureCompositionFrame.js";
|
||||
@@ -421,6 +422,7 @@ async function validateInBrowser(
|
||||
});
|
||||
|
||||
const page = await chromeBrowser.newPage();
|
||||
await installPageFunctionGuard(page);
|
||||
await page.setViewport(viewport);
|
||||
|
||||
page.on("console", (msg) => {
|
||||
|
||||
Reference in New Issue
Block a user