refactor(export): add lightning route policy plan

This commit is contained in:
wiiiii123
2026-05-22 18:27:10 +07:00
parent 9f896ec390
commit c87acf4b6d
2 changed files with 158 additions and 1 deletions
+52
View File
@@ -3,7 +3,9 @@ import { describe, expect, it } from "vitest";
import {
getDefaultLightningRenderBackend,
normalizeLightningRuntimePlatform,
planLightningExportRoutes,
shouldPreferNativeAutoBackend,
shouldPreferNativeStaticLayoutBeforeBreeze,
} from "./backendPolicy";
describe("backendPolicy", () => {
@@ -24,4 +26,54 @@ describe("backendPolicy", () => {
it("keeps Lightning exports on the stable WebGL renderer by default", () => {
expect(getDefaultLightningRenderBackend()).toBe("webgl");
});
it("puts visually compatible Windows auto exports on native static layout before Breeze", () => {
expect(shouldPreferNativeStaticLayoutBeforeBreeze("win32", "auto")).toBe(true);
expect(shouldPreferNativeStaticLayoutBeforeBreeze("darwin", "auto")).toBe(false);
expect(
planLightningExportRoutes({
backendPreference: "auto",
platform: "win32",
nativeStaticLayoutAvailable: true,
}),
).toMatchObject({
selectedRoute: "native-static-layout",
decisions: [
{ route: "native-static-layout", status: "selected" },
{ route: "breeze-stream", status: "fallback" },
{ route: "webcodecs", status: "fallback" },
],
});
});
it("documents the Breeze fallback when Windows static native is rejected", () => {
expect(
planLightningExportRoutes({
backendPreference: "auto",
platform: "win32",
nativeStaticLayoutAvailable: true,
nativeStaticLayoutSkipReasons: ["unsupported-frame-overlay"],
}),
).toEqual({
selectedRoute: "breeze-stream",
decisions: [
{
route: "native-static-layout",
status: "rejected",
reasons: ["unsupported-frame-overlay"],
},
{
route: "breeze-stream",
status: "selected",
reasons: ["windows-native-static-fallback"],
},
{
route: "webcodecs",
status: "fallback",
reasons: ["breeze-unavailable-fallback"],
},
],
});
});
});
+106 -1
View File
@@ -1,4 +1,4 @@
import type { ExportRenderBackend } from "./types";
import type { ExportBackendPreference, ExportRenderBackend } from "./types";
export type LightningRuntimePlatform = "darwin" | "win32" | "linux" | "unknown";
@@ -28,6 +28,111 @@ export function shouldPreferNativeAutoBackend(_platform: LightningRuntimePlatfor
return _platform === "darwin" || _platform === "win32";
}
export type LightningExportRoute = "native-static-layout" | "breeze-stream" | "webcodecs";
export interface LightningExportRouteDecision {
route: LightningExportRoute;
status: "selected" | "fallback" | "rejected";
reasons: string[];
}
export interface LightningExportRoutePlan {
selectedRoute: LightningExportRoute;
decisions: LightningExportRouteDecision[];
}
export function shouldPreferNativeStaticLayoutBeforeBreeze(
platform: LightningRuntimePlatform,
backendPreference: ExportBackendPreference,
): boolean {
return backendPreference === "auto" && platform === "win32";
}
export function planLightningExportRoutes(options: {
backendPreference: ExportBackendPreference;
platform: LightningRuntimePlatform;
nativeStaticLayoutAvailable: boolean;
nativeStaticLayoutSkipReasons?: string[];
}): LightningExportRoutePlan {
const decisions: LightningExportRouteDecision[] = [];
const nativeStaticLayoutSkipReasons = options.nativeStaticLayoutSkipReasons ?? [];
const canUseNativeStaticLayout =
options.nativeStaticLayoutAvailable && nativeStaticLayoutSkipReasons.length === 0;
const addNativeStaticLayoutDecision = (status: LightningExportRouteDecision["status"]) => {
decisions.push({
route: "native-static-layout",
status,
reasons: canUseNativeStaticLayout
? ["visually-compatible"]
: nativeStaticLayoutSkipReasons.length > 0
? nativeStaticLayoutSkipReasons
: ["native-static-unavailable"],
});
};
if (options.backendPreference === "webcodecs") {
decisions.push({
route: "webcodecs",
status: "selected",
reasons: ["user-selected-webcodecs"],
});
return { selectedRoute: "webcodecs", decisions };
}
const preferStaticFirst =
options.backendPreference === "breeze" ||
shouldPreferNativeStaticLayoutBeforeBreeze(options.platform, options.backendPreference);
if (preferStaticFirst) {
addNativeStaticLayoutDecision(canUseNativeStaticLayout ? "selected" : "rejected");
decisions.push({
route: "breeze-stream",
status: canUseNativeStaticLayout ? "fallback" : "selected",
reasons: [
options.backendPreference === "breeze"
? "user-selected-breeze"
: "windows-native-static-fallback",
],
});
decisions.push({
route: "webcodecs",
status: "fallback",
reasons: ["breeze-unavailable-fallback"],
});
return {
selectedRoute: canUseNativeStaticLayout ? "native-static-layout" : "breeze-stream",
decisions,
};
}
if (options.backendPreference === "auto" && shouldPreferNativeAutoBackend(options.platform)) {
decisions.push({
route: "breeze-stream",
status: "selected",
reasons: ["platform-prefers-native-streaming"],
});
decisions.push({
route: "webcodecs",
status: "fallback",
reasons: ["breeze-unavailable-fallback"],
});
return { selectedRoute: "breeze-stream", decisions };
}
decisions.push({
route: "webcodecs",
status: "selected",
reasons: ["default-webcodecs-first"],
});
decisions.push({
route: "breeze-stream",
status: "fallback",
reasons: ["webcodecs-software-or-unavailable-fallback"],
});
return { selectedRoute: "webcodecs", decisions };
}
export function getDefaultLightningRenderBackend(): ExportRenderBackend {
return "webgl";
}