@three-blocks/devtools 11.1.0 → 12.0.0-alpha.399.g24d19fd0f1a1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -0
- package/README.md +6 -2
- package/dist/{asset-optimize-YJGWKD4Y.js → asset-optimize-AC3RBHSK.js} +1 -1
- package/dist/browser/shader-capture.js +2 -2
- package/dist/browser-smoke-ZHNB3MIO.js +1 -0
- package/dist/{chunk-BBODS5RH.js → chunk-2SGYUV6P.js} +1 -1
- package/dist/chunk-75JSWKB4.js +2 -0
- package/dist/chunk-7YWPJCDF.cjs +1 -0
- package/dist/chunk-EX34XRLW.js +78 -0
- package/dist/chunk-HIS44NIG.js +23 -0
- package/dist/chunk-RITS37ER.js +1 -0
- package/dist/{chunk-S5LI2C2H.js → chunk-SNPGWQMW.js} +2 -2
- package/dist/chunk-UDMY6S4M.js +16 -0
- package/dist/chunk-UO6IYJA3.js +257 -0
- package/dist/chunk-WWBW6MPB.js +2 -0
- package/dist/cli.js +28 -27
- package/dist/index.d.ts +87 -48
- package/dist/index.js +1 -1
- package/dist/shader-browser-N5LY2NJX.js +1 -0
- package/dist/shader-capture-server.d.ts +13 -1
- package/dist/shader-capture-server.js +14 -14
- package/dist/{shader-config-AKZEKIRB.js → shader-config-TOBHWNCD.js} +1 -1
- package/dist/shader-workflow-JU5VYBN7.js +1 -0
- package/dist/status-CJTXLJBV.js +1 -0
- package/dist/transform.cjs +1 -1
- package/dist/transform.js +1 -1
- package/dist/webpack-loader.cjs +1 -1
- package/dist/webpack-loader.js +1 -1
- package/node/index.d.mts +2 -1
- package/node/index.mjs +10 -2
- package/node/layout.mjs +14 -2
- package/node/loader.mjs +5 -2
- package/node/worker.mjs +29 -6
- package/package.json +9 -4
- package/dist/browser-smoke-4MYMHKWB.js +0 -1
- package/dist/chunk-4SVF5BRM.js +0 -2
- package/dist/chunk-DCLDEPPB.js +0 -253
- package/dist/chunk-LMLJIVNY.cjs +0 -1
- package/dist/chunk-LSH64HEU.js +0 -80
- package/dist/chunk-NDIPQLTU.js +0 -16
- package/dist/chunk-NJITVI23.js +0 -2
- package/dist/chunk-O5FU2ASS.js +0 -16
- package/dist/chunk-QQKHDH26.js +0 -1
- package/dist/chunk-SBUKHO24.js +0 -1
- package/dist/shader-browser-6ICBHK3S.js +0 -1
- package/dist/shader-watch-JBUA4LP5.js +0 -1
- package/dist/shader-workflow-5EHHR32D.js +0 -1
- package/dist/status-GDVSLQWV.js +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -268,7 +268,7 @@ declare function ensureShaderToolConfig(root: string): Promise<EnsuredShaderTool
|
|
|
268
268
|
/** Published devtools protocol/package version. Kept dependency-free for instant CLI startup. */
|
|
269
269
|
declare const SHADER_DEVTOOLS_VERSION: "0.1.0";
|
|
270
270
|
|
|
271
|
-
declare const SHADER_PROVIDER_TRANSFORM_VERSION:
|
|
271
|
+
declare const SHADER_PROVIDER_TRANSFORM_VERSION: 65;
|
|
272
272
|
declare const SHADER_LOCAL_TIMING_FILE: "timing.local.json";
|
|
273
273
|
declare const SHADER_COMMITTED_TIMING_FILE: "timing.json";
|
|
274
274
|
declare const SHADER_PARITY_EVIDENCE_FILE: "parity.json";
|
|
@@ -355,6 +355,18 @@ interface ShaderCaptureStats {
|
|
|
355
355
|
readonly missedCompute: number;
|
|
356
356
|
/** Stable registered shader keys that fell back to a live build. */
|
|
357
357
|
readonly missedKeys?: readonly string[];
|
|
358
|
+
/** Verdict of a state-oracle observation; absent on every other lane. */
|
|
359
|
+
readonly stateOracle?: ShaderStateOracleStats;
|
|
360
|
+
}
|
|
361
|
+
/** Hydrated states compared with a live build of the same key in the same page. */
|
|
362
|
+
interface ShaderStateOracleStats {
|
|
363
|
+
readonly checked: number;
|
|
364
|
+
readonly equivalent: number;
|
|
365
|
+
/** Application nodes bound by both the hydrated state and the live build. */
|
|
366
|
+
readonly identical: number;
|
|
367
|
+
/** Application node recreated by hydration over the same value object. */
|
|
368
|
+
readonly recreated: number;
|
|
369
|
+
readonly differences: readonly string[];
|
|
358
370
|
}
|
|
359
371
|
interface ShaderCaptureStageTiming {
|
|
360
372
|
readonly launch?: number;
|
|
@@ -472,37 +484,28 @@ interface ShaderPublishedObservation extends ShaderBrowserObservation {
|
|
|
472
484
|
}
|
|
473
485
|
interface ShaderBrowserDriver {
|
|
474
486
|
capture(scene: ShaderSceneConfig, config: ShaderToolConfig, backend?: ShaderBackend): Promise<unknown>;
|
|
475
|
-
observe(scene: ShaderSceneConfig, mode: 'live' | 'precompiled', config: ShaderToolConfig, targetFrame?: number, backend?: ShaderBackend
|
|
487
|
+
observe(scene: ShaderSceneConfig, mode: 'live' | 'precompiled', config: ShaderToolConfig, targetFrame?: number, backend?: ShaderBackend,
|
|
488
|
+
/** Precompiled only: also live-build every hydrated key and report `stats.stateOracle`. */
|
|
489
|
+
stateOracle?: boolean): Promise<ShaderBrowserObservation>;
|
|
476
490
|
/** Observe the published route with strict precompiled telemetry enabled. */
|
|
477
491
|
observePublished(scene: ShaderSceneConfig, config: ShaderToolConfig, backend?: ShaderBackend): Promise<ShaderPublishedObservation>;
|
|
478
492
|
timingEnvironment?(): PromiseLike<ShaderTimingEnvironment> | ShaderTimingEnvironment;
|
|
479
493
|
close(): Promise<void>;
|
|
480
494
|
}
|
|
481
|
-
interface
|
|
495
|
+
interface ShaderDriverOptions {
|
|
482
496
|
readonly root: string;
|
|
483
497
|
readonly runtime: InstalledShaderRuntime;
|
|
484
498
|
readonly headed?: boolean;
|
|
485
|
-
}
|
|
486
|
-
interface StaticPlaywrightShaderDriverOptions extends PlaywrightShaderDriverOptions {
|
|
487
499
|
/** Project-relative directory containing the already-built application. */
|
|
488
|
-
readonly serve: string;
|
|
489
|
-
}
|
|
490
|
-
interface AttachedPlaywrightShaderDriverOptions extends PlaywrightShaderDriverOptions {
|
|
491
|
-
/** Already-running application origin or base URL. */
|
|
492
|
-
readonly url: string;
|
|
493
|
-
}
|
|
494
|
-
interface InternalPlaywrightShaderDriverOptions extends PlaywrightShaderDriverOptions {
|
|
495
500
|
readonly serve?: string;
|
|
501
|
+
/** Public path the application was built for (Vite `base`); the directory answers under it too. */
|
|
502
|
+
readonly base?: string;
|
|
503
|
+
/** Already-running application origin or base URL. */
|
|
496
504
|
readonly url?: string;
|
|
497
505
|
}
|
|
498
506
|
declare function isRetryableShaderObservationNavigation(error: unknown): boolean;
|
|
499
|
-
declare function createPlaywrightShaderDriver(options: PlaywrightShaderDriverOptions): ShaderBrowserDriver;
|
|
500
|
-
/** Capture and verify an already-built app without loading Vite from the target project. */
|
|
501
|
-
declare function createStaticPlaywrightShaderDriver(options: StaticPlaywrightShaderDriverOptions): ShaderBrowserDriver;
|
|
502
|
-
/** Attach capture and parity transport to an already-running transformed application. */
|
|
503
|
-
declare function createAttachedPlaywrightShaderDriver(options: AttachedPlaywrightShaderDriverOptions): ShaderBrowserDriver;
|
|
504
507
|
/** Shared Node capture/parity driver for every scene. */
|
|
505
|
-
declare function createShaderDriver(options:
|
|
508
|
+
declare function createShaderDriver(options: ShaderDriverOptions): ShaderBrowserDriver;
|
|
506
509
|
|
|
507
510
|
interface ShaderScreenshotMetrics {
|
|
508
511
|
readonly width: number;
|
|
@@ -624,6 +627,30 @@ interface CaptureShadersResult {
|
|
|
624
627
|
readonly written?: WrittenShaderArtifacts;
|
|
625
628
|
readonly timing?: ShaderTiming;
|
|
626
629
|
}
|
|
630
|
+
interface CaptureBuiltShadersOptions {
|
|
631
|
+
readonly root: string;
|
|
632
|
+
/** Built application directory, project-relative or absolute; its manifests are written inside it. */
|
|
633
|
+
readonly serve: string;
|
|
634
|
+
/** Public path the application was built for (Vite `base`). */
|
|
635
|
+
readonly base?: string;
|
|
636
|
+
readonly config?: ShaderToolConfig;
|
|
637
|
+
readonly runtime?: InstalledShaderRuntime;
|
|
638
|
+
readonly backend?: ShaderBackendSelection;
|
|
639
|
+
readonly onSceneStart?: CaptureShadersOptions['onSceneStart'];
|
|
640
|
+
readonly onSceneRetry?: CaptureShadersOptions['onSceneRetry'];
|
|
641
|
+
}
|
|
642
|
+
interface CaptureBuiltShadersResult {
|
|
643
|
+
readonly durationMs: number;
|
|
644
|
+
readonly scenes: readonly CaptureSceneResult[];
|
|
645
|
+
/** Project-relative manifests, one per scene and backend. */
|
|
646
|
+
readonly files: readonly string[];
|
|
647
|
+
}
|
|
648
|
+
/**
|
|
649
|
+
* Capture an already-built application and write `three-blocks/shaders/<scene>.<backend>.json`
|
|
650
|
+
* next to it, where the production runtime looks by convention. No receipt and no input
|
|
651
|
+
* hashes: the manifests describe exactly this bundle, and the next build replaces both.
|
|
652
|
+
*/
|
|
653
|
+
declare function captureBuiltShaders(options: CaptureBuiltShadersOptions): Promise<CaptureBuiltShadersResult>;
|
|
627
654
|
/** Run isolated browser captures and checkpoint updates against an existing complete matrix. */
|
|
628
655
|
declare function captureShaders(options?: CaptureShadersOptions): Promise<CaptureShadersResult>;
|
|
629
656
|
interface TestShadersOptions {
|
|
@@ -643,6 +670,11 @@ interface TestShadersOptions {
|
|
|
643
670
|
readonly runs?: number;
|
|
644
671
|
/** Run one live/precompiled correctness pair per scene without timing or published-page soak. */
|
|
645
672
|
readonly parityOnly?: boolean;
|
|
673
|
+
/**
|
|
674
|
+
* With `parityOnly`: also run the state oracle on pairs whose pixels agree, and fail a
|
|
675
|
+
* pair whose hydrated state differs from a live build. A pixel failure always runs it.
|
|
676
|
+
*/
|
|
677
|
+
readonly stateOracle?: boolean;
|
|
646
678
|
/** Also write the opt-in, hardware-labeled committed timing twin. */
|
|
647
679
|
readonly commitTiming?: boolean;
|
|
648
680
|
/** Progress hook fired before each scene observation begins. */
|
|
@@ -675,7 +707,6 @@ interface TestShadersResult {
|
|
|
675
707
|
readonly timing?: ShaderLocalTiming;
|
|
676
708
|
readonly committedTiming?: ShaderCommittedTiming;
|
|
677
709
|
}
|
|
678
|
-
/** Validate freshness, zero registered builds (render and compute), and deterministic pixels. */
|
|
679
710
|
declare function testShaders(options?: TestShadersOptions): Promise<TestShadersResult>;
|
|
680
711
|
|
|
681
712
|
type ShaderState = 'precompiled' | 'live' | 'stale' | 'invalid' | 'missing';
|
|
@@ -1111,6 +1142,12 @@ interface BrowserSmokeReport {
|
|
|
1111
1142
|
readonly resolved: readonly string[];
|
|
1112
1143
|
};
|
|
1113
1144
|
}
|
|
1145
|
+
/** Shader provider counters of one page: hydrated states, provider misses, and live TSL builds. */
|
|
1146
|
+
interface BrowserShaderCounters {
|
|
1147
|
+
readonly injected: number;
|
|
1148
|
+
readonly missed: number;
|
|
1149
|
+
readonly live: number;
|
|
1150
|
+
}
|
|
1114
1151
|
/** Parse the public smoke bridge, with a bounded compatibility path for the integration lab. */
|
|
1115
1152
|
declare function parseBrowserSmokeLifecycle(snapshot: unknown, textEnabled: boolean): BrowserSmokeLifecycle;
|
|
1116
1153
|
declare function screenshotLuminance(bytes: Uint8Array): number;
|
|
@@ -1136,12 +1173,18 @@ interface BrowserPreviewOptions {
|
|
|
1136
1173
|
};
|
|
1137
1174
|
/** Minimum mean center-frame or readable-panel luminance. Defaults to 2. */
|
|
1138
1175
|
readonly minimumLuminance?: number;
|
|
1176
|
+
/** Project-relative directory that receives one PNG of each route's settled frame. */
|
|
1177
|
+
readonly screenshots?: string;
|
|
1139
1178
|
}
|
|
1140
1179
|
interface BrowserPreviewRouteReport {
|
|
1141
1180
|
readonly route: string;
|
|
1142
1181
|
readonly passed: boolean;
|
|
1143
1182
|
readonly lifecycle: BrowserSmokeLifecycle;
|
|
1144
1183
|
readonly shaderMode: 'precompiled' | 'live' | null;
|
|
1184
|
+
/** `live` above zero names shaders the bundle still compiles in the visitor's browser. */
|
|
1185
|
+
readonly shaders?: BrowserShaderCounters;
|
|
1186
|
+
/** Project-relative PNG of the settled frame, when `screenshots` was given. */
|
|
1187
|
+
readonly screenshot?: string;
|
|
1145
1188
|
readonly rendering: {
|
|
1146
1189
|
readonly luminance: number;
|
|
1147
1190
|
readonly panelLuminance: number;
|
|
@@ -1169,6 +1212,30 @@ interface BrowserPreviewReport {
|
|
|
1169
1212
|
* the gate that catches precompiled-shader hydration regressions in shipped output.
|
|
1170
1213
|
*/
|
|
1171
1214
|
declare function runBrowserPreview(options: BrowserPreviewOptions): Promise<BrowserPreviewReport>;
|
|
1215
|
+
interface ProjectCheckReport {
|
|
1216
|
+
readonly schemaVersion: 1;
|
|
1217
|
+
readonly command: 'check';
|
|
1218
|
+
readonly passed: boolean;
|
|
1219
|
+
/** `ran` is false when the project has no `tsconfig.json` or no local TypeScript. */
|
|
1220
|
+
readonly typecheck: {
|
|
1221
|
+
readonly ran: boolean;
|
|
1222
|
+
readonly passed: boolean;
|
|
1223
|
+
readonly diagnostics: readonly string[];
|
|
1224
|
+
};
|
|
1225
|
+
/** Absent when the production build itself failed; `error` then says why. */
|
|
1226
|
+
readonly preview?: BrowserPreviewReport;
|
|
1227
|
+
readonly error?: string;
|
|
1228
|
+
}
|
|
1229
|
+
/**
|
|
1230
|
+
* The one verification to run after an edit: the project's types, then its real production
|
|
1231
|
+
* bundle, built once (which captures its shaders) and booted natively per configured scene.
|
|
1232
|
+
* Each route reports its console errors, the shaders it still compiles live, and the PNG of
|
|
1233
|
+
* its settled frame under `.three-blocks/check/`, which is how an agent sees its change.
|
|
1234
|
+
*/
|
|
1235
|
+
declare function runProjectCheck(options: {
|
|
1236
|
+
readonly root: string;
|
|
1237
|
+
}): Promise<ProjectCheckReport>;
|
|
1238
|
+
declare function formatProjectCheckReport(report: ProjectCheckReport): string;
|
|
1172
1239
|
declare function formatBrowserPreviewReport(report: BrowserPreviewReport): string;
|
|
1173
1240
|
|
|
1174
1241
|
declare const ENVIRONMENT_BAKE_VERSION: 1;
|
|
@@ -1231,34 +1298,6 @@ declare function formatEnvironmentBakeReport(report: EnvironmentBakeReport): str
|
|
|
1231
1298
|
|
|
1232
1299
|
declare function loadShaderCaptureRuntimeSource(): Promise<string>;
|
|
1233
1300
|
|
|
1234
|
-
interface ShaderWatchQueueOptions {
|
|
1235
|
-
readonly capture: () => Promise<void>;
|
|
1236
|
-
readonly debounceMs?: number;
|
|
1237
|
-
readonly onError?: (error: Error) => void;
|
|
1238
|
-
}
|
|
1239
|
-
/** Debounced capture queue with at most one running capture and one queued rerun. */
|
|
1240
|
-
declare class ShaderWatchQueue {
|
|
1241
|
-
#private;
|
|
1242
|
-
constructor(options: ShaderWatchQueueOptions);
|
|
1243
|
-
notify(): void;
|
|
1244
|
-
close(): Promise<void>;
|
|
1245
|
-
}
|
|
1246
|
-
interface WatchShadersOptions extends Omit<CaptureShadersOptions, 'root' | 'ifStale'> {
|
|
1247
|
-
readonly root?: string;
|
|
1248
|
-
readonly debounceMs?: number;
|
|
1249
|
-
readonly signal?: AbortSignal;
|
|
1250
|
-
readonly onResult?: (result: CaptureShadersResult) => void;
|
|
1251
|
-
readonly onError?: (error: Error) => void;
|
|
1252
|
-
readonly initial?: boolean;
|
|
1253
|
-
}
|
|
1254
|
-
interface ShaderWatchSession {
|
|
1255
|
-
readonly root: string;
|
|
1256
|
-
readonly done: Promise<void>;
|
|
1257
|
-
close(): Promise<void>;
|
|
1258
|
-
}
|
|
1259
|
-
/** Opt-in filesystem watch. A failed recapture leaves the prior receipt in place and watching continues. */
|
|
1260
|
-
declare function watchShaders(options?: WatchShadersOptions): Promise<ShaderWatchSession>;
|
|
1261
|
-
|
|
1262
1301
|
/**
|
|
1263
1302
|
* Asset optimization: meshopt geometry + slot-aware Basis Universal (KTX2)
|
|
1264
1303
|
* textures for GLB/image/HDR inputs, with a content-hash encode cache and a
|
|
@@ -1366,4 +1405,4 @@ interface AssetStatusReport {
|
|
|
1366
1405
|
declare function inspectAssets(root: string): Promise<AssetStatusReport>;
|
|
1367
1406
|
declare function formatAssetStatusReport(report: AssetStatusReport): string;
|
|
1368
1407
|
|
|
1369
|
-
export { ASSET_OPTIMIZE_VERSION, ASSET_RECEIPT_DIRECTORY, ASSET_RECEIPT_FILE, type AdoptedProjectStatus, type ArtifactState, type AssetKind, type AssetOptimizeOptions, type AssetOptimizeReport, type AssetState, type AssetStatusEntry, type AssetStatusReport, type
|
|
1408
|
+
export { ASSET_OPTIMIZE_VERSION, ASSET_RECEIPT_DIRECTORY, ASSET_RECEIPT_FILE, type AdoptedProjectStatus, type ArtifactState, type AssetKind, type AssetOptimizeOptions, type AssetOptimizeReport, type AssetState, type AssetStatusEntry, type AssetStatusReport, type BrowserPreviewOptions, type BrowserPreviewReport, type BrowserPreviewRouteReport, type BrowserShaderCounters, type BrowserSmokeBuildReceipt, type BrowserSmokeCodec, type BrowserSmokeCodecRoute, type BrowserSmokeHmr, type BrowserSmokeHmrEvidence, type BrowserSmokeLifecycle, type BrowserSmokeOptions, type BrowserSmokeReport, type BrowserSmokeWorkerRestart, type BuiltinFontMetadata, type CaptureBuiltShadersOptions, type CaptureBuiltShadersResult, type CaptureSceneResult, type CaptureShadersOptions, type CaptureShadersResult, DOCUMENTED_BROWSER_NOISE, type DiscoveredTextContent, type EncodedRoomEnvironment, type EnsuredShaderToolConfig, type EnvironmentBakeOptions, type EnvironmentBakeReport, type FailedAssetResult, type GenerateTextResult, type GeneratedTextAtlas, type GlyphSet, type GlyphSetOptions, type InferredShaderCaptureTarget, type InstalledShaderRuntime, type OptimizedAssetResult, type ProjectCheckReport, type ProjectMetadataV2, type ProjectStatus, RUNTIME_STATUS_RECEIPT_MAX_BYTES, RUNTIME_STATUS_RECEIPT_PATH, RUNTIME_STATUS_RECOVERY, type RoomEnvironmentCapture, type RoomEnvironmentCaptureOptions, type RoomEnvironmentCaptureResult, type RoomEnvironmentMetadata, type RuntimeAssetsStatus, type RuntimeBackend, type RuntimeCodecObservation, type RuntimeHmrCapabilities, type RuntimeHmrOutcome, type RuntimeHmrStatus, type RuntimeObservation, type RuntimeOptimizationStatus, type RuntimeState, type RuntimeStatsStatus, type RuntimeStatusReceiptV1, type RuntimeTextStatus, type RuntimeWorkerStatus, SHADER_ARTIFACT_DIRECTORY, SHADER_COMMITTED_TIMING_FILE, SHADER_DEVTOOLS_VERSION, SHADER_LOCAL_TIMING_FILE, SHADER_PARITY_DIRECTORY, SHADER_PARITY_EVIDENCE_FILE, SHADER_PROVIDER_TRANSFORM_VERSION, SHADER_TOOL_CONFIG_FILE, type ShaderBridgeConfig, type ShaderBrowserDriver, type ShaderBrowserObservation, type ShaderBrowserReadiness, type ShaderCapturePayload, type ShaderCaptureProvenance, type ShaderCaptureStageTiming, type ShaderCaptureStats, type ShaderCommittedTiming, type ShaderCoverage, type ShaderDriverOptions, type ShaderFreshness, type ShaderLocalTiming, type ShaderMatrixState, type ShaderMatrixStatus, type ShaderParityConfig, type ShaderParityEvidence, type ShaderParityResult, type ShaderReadinessConfig, type ShaderReceiptV2, type ShaderSceneArtifactStatus, type ShaderSceneConfig, type ShaderSceneParityEvidence, type ShaderSceneReceipt, type ShaderSceneTestResult, type ShaderSceneTiming, type ShaderScreenshotMetrics, type ShaderSkippedBuild, type ShaderStartupMeasurement, type ShaderState, type ShaderStatus, type ShaderTiming, type ShaderTimingEnvironment, type ShaderToolConfig, TEXT_ATLAS_GENERATOR_VERSION, TEXT_ATLAS_SCHEMA_VERSION, type TestShadersOptions, type TestShadersResult, type TextAtlasFileReceipt, type TextAtlasGenerationReceipt, type TextAtlasInspection, type TextAtlasRuntimeOptions, type TextAtlasStatus, type TextState, type TextStatus, type TextUnicodePreset, type TextUnicodeRange, type TextureEncodeMode, type TextureEncodeResult, type TexturePreset, type ThreeBlocksStatus, type ToolTextConfiguration, type ToolTextFontRoute, type ToolTextFontSource, type ToolTextGenerationOptions, type ValidateShaderCaptureOptions, type ValidatedShaderCapture, type WriteShaderArtifactsOptions, type WrittenShaderArtifacts, bakeRoomEnvironment, buildGlyphSet, builtinFontMetadata, captureBuiltShaders, captureRoomEnvironment, captureShaders, compareShaderScreenshots, createShaderDriver, discoverPublicAssets, discoverTextContent, encodeRoomEnvironmentKtx2, ensureShaderToolConfig, extractCanvasTextFromHtml, extractDefinedTextContent, findProjectRoot, findShaderProjectRoot, formatAssetOptimizeReport, formatAssetStatusReport, formatBrowserPreviewReport, formatBrowserSmokeReport, formatEnvironmentBakeReport, formatProjectCheckReport, formatShaderMatrixStatus, formatStatus, formatThreeBlocksStatus, generateTextAtlases, inferShaderCaptureTarget, inspectAssets, inspectProject, inspectShaderMatrix, inspectTextAtlases, inspectThreeBlocksStatus, isDocumentedBrowserNoise, isRetryableShaderObservationNavigation, loadShaderCaptureRuntimeSource, loadShaderToolConfig, optimizeAssets, parseBrowserSmokeLifecycle, parseProjectMetadata, parseRuntimeStatusReceipt, parseShaderReceipt, parseShaderToolConfig, parseTextAtlasReceipt, parseTextConfiguration, presetForImageName, presetForTextureSlots, prewarmBuiltinFont, readInstalledShaderRuntime, readShaderCommittedTiming, readShaderLocalTiming, readShaderParityEvidence, readShaderTiming, readTextConfiguration, runBrowserPreview, runBrowserSmoke, runProjectCheck, screenshotLuminance, serializeShaderManifest, shaderCoverage, shaderScreenshotMetrics, snapshotShaderInputs, stableStringify, testShaders, threeBlocksStatusIsFresh, validateEnvironmentCubeSize, validateShaderCapture, webgpuBrowserArgs, webgpuBrowserHeadless, writeShaderArtifacts, writeShaderLocalTiming, writeShaderParityEvidence, writeShaderTimingTwins };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export{
|
|
1
|
+
export{k as formatBrowserPreviewReport,g as formatBrowserSmokeReport,j as formatProjectCheckReport,a as parseBrowserSmokeLifecycle,h as runBrowserPreview,f as runBrowserSmoke,i as runProjectCheck,b as screenshotLuminance}from'./chunk-UO6IYJA3.js';export{b as RUNTIME_STATUS_RECEIPT_MAX_BYTES,a as RUNTIME_STATUS_RECEIPT_PATH,c as RUNTIME_STATUS_RECOVERY,e as findProjectRoot,i as formatShaderMatrixStatus,j as formatStatus,k as formatThreeBlocksStatus,f as inspectProject,g as inspectThreeBlocksStatus,d as parseRuntimeStatusReceipt,h as threeBlocksStatusIsFresh}from'./chunk-2SGYUV6P.js';export{e as captureBuiltShaders,f as captureShaders,d as inspectShaderMatrix,c as readInstalledShaderRuntime,b as snapshotShaderInputs,h as testShaders}from'./chunk-HIS44NIG.js';export{d as bakeRoomEnvironment,c as captureRoomEnvironment,b as encodeRoomEnvironmentKtx2,e as formatEnvironmentBakeReport,a as validateEnvironmentCubeSize}from'./chunk-IWQV456Z.js';export{a as ASSET_OPTIMIZE_VERSION,b as ASSET_RECEIPT_DIRECTORY,c as ASSET_RECEIPT_FILE,h as discoverPublicAssets,g as formatAssetOptimizeReport,j as formatAssetStatusReport,i as inspectAssets,f as optimizeAssets,e as presetForImageName,d as presetForTextureSlots}from'./chunk-SNPGWQMW.js';import'./chunk-CMMYXGQ3.js';export{h as TEXT_ATLAS_GENERATOR_VERSION,g as TEXT_ATLAS_SCHEMA_VERSION,c as buildGlyphSet,i as builtinFontMetadata,f as discoverTextContent,a as extractCanvasTextFromHtml,b as extractDefinedTextContent,k as generateTextAtlases,m as inspectTextAtlases,l as parseTextAtlasReceipt,d as parseTextConfiguration,j as prewarmBuiltinFont,e as readTextConfiguration}from'./chunk-MIJXPQPM.js';export{f as createShaderDriver,e as isRetryableShaderObservationNavigation}from'./chunk-EX34XRLW.js';export{a as DOCUMENTED_BROWSER_NOISE,b as isDocumentedBrowserNoise,c as webgpuBrowserArgs,d as webgpuBrowserHeadless}from'./chunk-ZG3LO3VB.js';export{b as SHADER_CAPTURE_CLIENT_ID,e as applyShaderProviderTransform,g as assertShaderProviderTransform,f as createShaderProviderTransform,a as loadShaderCaptureRuntimeSource}from'./chunk-WWBW6MPB.js';export{d as SHADER_COMMITTED_TIMING_FILE,c as SHADER_LOCAL_TIMING_FILE,e as SHADER_PARITY_EVIDENCE_FILE,b as SHADER_PROVIDER_TRANSFORM_VERSION,n as readShaderCommittedTiming,k as readShaderLocalTiming,m as readShaderParityEvidence,l as readShaderTiming,j as serializeShaderManifest,g as shaderCoverage,i as stableStringify,h as validateShaderCapture,s as writeShaderArtifacts,o as writeShaderLocalTiming,p as writeShaderParityEvidence,r as writeShaderTimingTwins}from'./chunk-UDMY6S4M.js';export{a as SHADER_DEVTOOLS_VERSION}from'./chunk-TK566QET.js';export{b as SHADER_ARTIFACT_DIRECTORY,c as SHADER_PARITY_DIRECTORY,a as SHADER_TOOL_CONFIG_FILE,l as ensureShaderToolConfig,i as findShaderProjectRoot,k as inferShaderCaptureTarget,j as loadShaderToolConfig,h as parseShaderToolConfig}from'./chunk-75JSWKB4.js';export{b as parseProjectMetadata,c as parseShaderReceipt}from'./chunk-WNSGAV6N.js';import'./chunk-ECQE4D2U.js';export{b as compareShaderScreenshots,a as shaderScreenshotMetrics}from'./chunk-ZTHZE36A.js';import'./chunk-7X4DHW36.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{d as canReuseShaderBrowserSession,f as createShaderDriver,e as isRetryableShaderObservationNavigation,c as publicBridgeScript,b as settleShaderParityFrames,a as waitForShaderCaptureAcrossNavigation}from'./chunk-EX34XRLW.js';import'./chunk-ZG3LO3VB.js';import'./chunk-WWBW6MPB.js';import'./chunk-UDMY6S4M.js';import'./chunk-TK566QET.js';import'./chunk-75JSWKB4.js';import'./chunk-WNSGAV6N.js';import'./chunk-ECQE4D2U.js';import'./chunk-7X4DHW36.js';
|
|
@@ -181,7 +181,7 @@ interface ShaderMatrixStatus {
|
|
|
181
181
|
/** Inspect all configured manifests without launching Vite, a browser, or a GPU. */
|
|
182
182
|
declare function inspectShaderMatrix(start?: string, runtimeOverride?: InstalledShaderRuntime, backendOverride?: ShaderBackendSelection): Promise<ShaderMatrixStatus>;
|
|
183
183
|
|
|
184
|
-
declare const SHADER_PROVIDER_TRANSFORM_VERSION:
|
|
184
|
+
declare const SHADER_PROVIDER_TRANSFORM_VERSION: 65;
|
|
185
185
|
interface ShaderSceneTiming {
|
|
186
186
|
/** Number of registered render/compute NodeBuilder builds covered by the manifest. */
|
|
187
187
|
readonly builds: number;
|
|
@@ -251,6 +251,18 @@ interface ShaderCaptureStats {
|
|
|
251
251
|
readonly missedCompute: number;
|
|
252
252
|
/** Stable registered shader keys that fell back to a live build. */
|
|
253
253
|
readonly missedKeys?: readonly string[];
|
|
254
|
+
/** Verdict of a state-oracle observation; absent on every other lane. */
|
|
255
|
+
readonly stateOracle?: ShaderStateOracleStats;
|
|
256
|
+
}
|
|
257
|
+
/** Hydrated states compared with a live build of the same key in the same page. */
|
|
258
|
+
interface ShaderStateOracleStats {
|
|
259
|
+
readonly checked: number;
|
|
260
|
+
readonly equivalent: number;
|
|
261
|
+
/** Application nodes bound by both the hydrated state and the live build. */
|
|
262
|
+
readonly identical: number;
|
|
263
|
+
/** Application node recreated by hydration over the same value object. */
|
|
264
|
+
readonly recreated: number;
|
|
265
|
+
readonly differences: readonly string[];
|
|
254
266
|
}
|
|
255
267
|
interface ShaderCaptureStageTiming {
|
|
256
268
|
readonly launch?: number;
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import {realpath,readFile,mkdir,readdir,unlink,lstat,open,rename,rm}from'fs/promises';import b from'path';import {parsePrecompiledManifest,SHADER_HYDRATION_SCHEMA_VERSION,SHADER_RECIPE_SCHEMA_VERSION,SHADER_ADDRESS_SCHEMA_VERSION,PRECOMPILED_MANIFEST_VERSION,THREE_WEBGL_R185_COMPATIBILITY,THREE_WEBGPU_R185_COMPATIBILITY,THREE_R186DEV_VERSION,THREE_WEBGPU_R186DEV_COMPATIBILITY}from'three-blocks/shaders';import {createHash,randomUUID}from'crypto';import {createRequire}from'module';var kt=Object.defineProperty;var o=(e,t)=>kt(e,"name",{value:t,configurable:true});var $=Object.freeze({metadata:1024*1024,receipt:2*1024*1024,manifest:32*1024*1024,semanticInput:8*1024*1024,semanticTotal:64*1024*1024,metrics:8*1024*1024,texture:128*1024*1024,packageJson:1024*1024});function De(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"?e.code:void 0}o(De,"errorCode");function I(e){return createHash("sha256").update(e).digest("hex")}o(I,"sha256");async function C(e){try{return await lstat(e),!0}catch(t){if(De(t)==="ENOENT")return false;throw t}}o(C,"pathExists");function v(e,t){let r=b.relative(e,t);return r===""||!b.isAbsolute(r)&&r!==".."&&!r.startsWith(`..${b.sep}`)}o(v,"isWithin");function z(e){return JSON.stringify(e)}o(z,"displayPath");async function Fe(e,t,r){let n=await open(e,"r");try{let[i,s,a]=await Promise.all([lstat(e),n.stat(),realpath(e)]);if(i.isSymbolicLink())throw new Error(`${r} must not be a symbolic link: ${z(e)}.`);if(!s.isFile())throw new Error(`${r} must be a regular file: ${z(e)}.`);if(s.size>t)throw new Error(`${r} exceeds the ${t}-byte inspection limit: ${z(e)}.`);let c=await n.readFile();if(c.byteLength>t)throw new Error(`${r} grew beyond the ${t}-byte inspection limit while being read.`);return {path:a,data:c}}finally{await n.close();}}o(Fe,"readBoundedRegularFile");async function ce(e,t){let r=b.dirname(e);await mkdir(r,{recursive:true});try{if((await lstat(e)).isSymbolicLink())throw new Error(`Atomic write target must not be a symbolic link: ${z(e)}.`)}catch(s){if(De(s)!=="ENOENT")throw s}let n=b.join(r,`.${b.basename(e)}.${process.pid}.${randomUUID()}.tmp`),i;try{i=await open(n,"wx",384),await i.writeFile(t),await i.sync(),await i.close(),i=void 0,await rename(n,e);}finally{await i?.close().catch(()=>{}),await rm(n,{force:true});}}o(ce,"writeAtomicRegularFile");async function ye(e,t,r){return Fe(e,t,r)}o(ye,"readExternalRegularFile");async function U(e,t,r){let n=b.resolve(e),i=b.resolve(t);if(!v(n,i))throw new Error(`${r} escapes its allowed directory.`);let s=await lstat(i);if(s.isSymbolicLink())throw new Error(`${r} must not be a symbolic link.`);if(!s.isDirectory())throw new Error(`${r} must be a directory.`);let[a,c]=await Promise.all([realpath(n),realpath(i)]);if(!v(a,c))throw new Error(`${r} resolves outside its allowed directory.`);return c}o(U,"canonicalDirectoryWithin");async function B(e,t,r,n){let i=b.resolve(e),s=b.resolve(t);if(!v(i,s)||i===s)throw new Error(`${n} escapes its allowed directory.`);let a=await Fe(s,r,n),c=await realpath(i);if(!v(c,a.path)||c===a.path)throw new Error(`${n} resolves outside its allowed directory.`);return a}o(B,"readRegularFileWithin");async function Ve(e,t,r,n=8192){let s=[await U(e,t,"Inspected directory")],a=[],c=0;for(;s.length>0;){let f=s.shift();if(f===void 0)break;let m=(await readdir(f,{withFileTypes:true})).sort((h,d)=>h.name.localeCompare(d.name));for(let h of m){if(c+=1,c>n)throw new Error(`Inspected directory exceeds the ${n}-entry limit.`);let d=b.join(f,h.name);if(h.isSymbolicLink())throw new Error(`Inspected directory contains a symbolic link: ${z(b.relative(e,d))}.`);if(h.isDirectory()){s.push(await U(e,d,"Nested inspected directory"));continue}if(h.isFile()&&r(h.name))a.push(d);else if(r(h.name))throw new Error(`Semantic input is not a regular file: ${z(d)}.`)}}return a.sort()}o(Ve,"listRegularFilesRecursively");var ue=/^[a-f0-9]{64}$/,Mt=/^[0-9A-Za-z][0-9A-Za-z.+_-]{0,127}$/,He=/^[a-z0-9][a-z0-9_-]{0,63}$/,ve=/^[0-9A-Za-z][0-9A-Za-z._/-]{0,127}$/;function l(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}o(l,"isRecord");function W(e){return typeof e=="string"&&Mt.test(e)}o(W,"isSafeVersion");function Se(e){if(e.length===0||e.length>512||e.includes("\\")||/[\u0000-\u001f\u007f]/.test(e))return false;let t=e.split("/");return !e.startsWith("/")&&t.every(r=>r.length>0&&r!=="."&&r!=="..")}o(Se,"isSafeRelativePath");function ze(e){if(!l(e)||e.schemaVersion!==2)throw new Error("three-blocks.json must use schemaVersion 2.");if(typeof e.template!="string"||!He.test(e.template))throw new Error("three-blocks.json has an invalid default shader scene key.");if(!Array.isArray(e.layers)||!e.layers.every(t=>typeof t=="string"&&ve.test(t))||new Set(e.layers).size!==e.layers.length)throw new Error("three-blocks.json has invalid layers.");if(e.generator!==void 0&&(!l(e.generator)||typeof e.generator.name!="string"||!ve.test(e.generator.name)||!W(e.generator.version)))throw new Error("three-blocks.json has invalid generator metadata.");if(!l(e.runtime)||!W(e.runtime.three)||!W(e.runtime.threeBlocks))throw new Error("three-blocks.json has invalid runtime versions.");if(!l(e.features)||typeof e.features.text!="boolean")throw new Error("three-blocks.json has invalid feature metadata.");if(!l(e.protocol)||e.protocol.resultFile!==1)throw new Error("three-blocks.json has an unsupported protocol schema.");if(e.artifacts!==void 0){if(!l(e.artifacts)||typeof e.artifacts.shaders!="string"||!["fresh","pending"].includes(e.artifacts.shaders)||typeof e.artifacts.text!="string"||!["fresh","pending","not-applicable"].includes(e.artifacts.text))throw new Error("three-blocks.json has invalid artifact metadata.");if(e.features.text?e.artifacts.text==="not-applicable":e.artifacts.text!=="not-applicable")throw new Error("three-blocks.json text artifact state does not match the text capability.")}return {schemaVersion:2,template:e.template,layers:e.layers,...e.generator===void 0?{}:{generator:{name:e.generator.name,version:e.generator.version}},runtime:{three:e.runtime.three,threeBlocks:e.runtime.threeBlocks},features:{text:e.features.text},...e.artifacts===void 0?{}:{artifacts:{shaders:e.artifacts.shaders,text:e.artifacts.text}},protocol:{resultFile:1}}}o(ze,"parseProjectMetadata");function Ct(e){if(!l(e))throw new Error("Shader coverage is missing.");for(let t of ["render","vertex","fragment","compute"])if(typeof e[t]!="number"||!Number.isSafeInteger(e[t])||e[t]<0)throw new Error(`Shader coverage.${t} must be a non-negative integer.`);return e}o(Ct,"parseCoverage");function It(e,t){if(!l(e))throw new Error(`Shader receipt inputs for "${t}" are invalid.`);let r=Object.entries(e);if(r.length===0||r.length>4096)throw new Error(`Shader receipt inputs for "${t}" must contain between 1 and 4096 files.`);for(let[n,i]of r)if(!Se(n)||typeof i!="string"||!ue.test(i))throw new Error(`Shader receipt input for "${t}" is invalid.`)}o(It,"parseInputs");function le(e){if(!l(e)||e.schemaVersion!==2||!l(e.runtime)||!W(e.runtime.three)||!W(e.runtime.threeBlocks)||typeof e.runtime.threeBlocksShaderClosure!="string"||!ue.test(e.runtime.threeBlocksShaderClosure)||!l(e.scenes))throw new Error("Shader meta.json does not match receipt schema 2.");if(e.runtime.capture!==void 0&&(!l(e.runtime.capture)||typeof e.runtime.capture.userAgent!="string"||e.runtime.capture.userAgent.length>1024||typeof e.runtime.capture.adapter!="string"||e.runtime.capture.adapter.length>1024||!Array.isArray(e.runtime.capture.features)||e.runtime.capture.features.length>256||!e.runtime.capture.features.every(r=>typeof r=="string"&&r.length>0&&r.length<=128)))throw new Error("Shader meta.json has invalid browser capture provenance.");let t=Object.entries(e.scenes);if(t.length===0)throw new Error("Shader meta.json contains no scenes.");for(let[r,n]of t){let i=r.endsWith(".webgl")?"webgl":"webgpu",s=i==="webgl"?r.slice(0,-6):r;if(!He.test(s)||!l(n)||n.backend!==void 0&&n.backend!==i||typeof n.artifact!="string"||!Se(n.artifact)||!n.artifact.endsWith(`.${i}.ts`)||typeof n.artifactHash!="string"||!ue.test(n.artifactHash))throw new Error(`Shader receipt for "${r}" is invalid.`);if(n.asset===void 0!=(n.assetHash===void 0)||n.asset!==void 0&&(typeof n.asset!="string"||!Se(n.asset)||!n.asset.endsWith(".json")||typeof n.assetHash!="string"||!ue.test(n.assetHash)))throw new Error(`Shader static asset receipt for "${r}" is invalid.`);if(It(n.inputs,r),Ct(n.coverage),n.bytes!==void 0&&(!Number.isSafeInteger(n.bytes)||Number(n.bytes)<0))throw new Error(`Shader receipt byte count for "${r}" is invalid.`);if(n.skipped!==void 0&&(!l(n.skipped)||!Number.isSafeInteger(n.skipped.render)||Number(n.skipped.render)<0||!Number.isSafeInteger(n.skipped.compute)||Number(n.skipped.compute)<0))throw new Error(`Shader receipt skipped-build counts for "${r}" are invalid.`)}if(e.tool!==void 0&&(!l(e.tool)||e.tool.name!=="@three-blocks/devtools"||!W(e.tool.version)||typeof e.tool.compatibility!="string"||!Number.isSafeInteger(e.tool.transform)||!Number.isSafeInteger(e.tool.address)||!Number.isSafeInteger(e.tool.recipe)||!Number.isSafeInteger(e.tool.hydration)))throw new Error("Shader meta.json has invalid tool compatibility metadata.");if(l(e.tool)&&e.tool.compatibilities!==void 0&&(!l(e.tool.compatibilities)||Object.entries(e.tool.compatibilities).some(([r,n])=>r!=="webgpu"&&r!=="webgl"||typeof n!="string"||n.length===0)))throw new Error("Shader meta.json has invalid backend compatibility metadata.");return e}o(le,"parseShaderReceipt");var Je="three-blocks.shaders.json",Ee=".three-blocks/shaders";var Bt=/^[a-z0-9][a-z0-9_-]{0,63}$/u,Pt=/^[A-Za-z_$][A-Za-z0-9_$]*(?:\.[A-Za-z_$][A-Za-z0-9_$]*)*$/u,Ue=64,We=64,Ot={schemaVersion:1,backend:"both",scenes:[{key:"default",url:"/"}]};function qe(e="both"){return e==="both"?["webgpu","webgl"]:[e]}o(qe,"shaderBackends");function J(e,t){return e.backend===void 0?t:t.filter(r=>r===e.backend)}o(J,"shaderSceneBackends");function K(e,t){return t==="webgpu"?e:`${e}.webgl`}o(K,"shaderReceiptKey");function Ge(e,t,r){if(e===void 0)return r;if(typeof e!="string"||e.length===0||e.length>512||b.isAbsolute(e)||/[\u0000-\u001f\u007f]/u.test(e))throw new Error(`${t} must be a bounded project-relative directory.`);let n=b.posix.normalize(e.replaceAll("\\","/")).replace(/\/+$/u,"");if(n==="."||n===".."||n.startsWith("../"))throw new Error(`${t} must stay inside the project.`);return n}o(Ge,"safeProjectDirectory");function Nt(e,t){let r=Ge(e,t,"");if(typeof e!="string"||e.endsWith("/"))throw new Error(`${t} must be a project-relative file.`);return r}o(Nt,"safeProjectFile");function L(e,t,r,n,i){if(e===void 0)return i;if(!Number.isSafeInteger(e)||Number(e)<r||Number(e)>n)throw new Error(`${t} must be an integer in ${r}...${n}.`);return Number(e)}o(L,"boundedInteger");function Ke(e,t,r){if(e===void 0)return r;if(typeof e!="number"||!Number.isFinite(e)||e<0||e>1)throw new Error(`${t} must be a finite ratio in 0...1.`);return e}o(Ke,"finiteRatio");function Ye(e,t){if(typeof e!="string"||e.length===0||e.length>2048||/[\u0000-\u001f\u007f]/u.test(e))throw new Error(`${t} must be a bounded project-relative URL.`);let r;try{r=new URL(e,"http://three-blocks.invalid/");}catch{throw new Error(`${t} is not a valid URL.`)}if(r.origin!=="http://three-blocks.invalid"||r.hash.length>0)throw new Error(`${t} must stay within the project and must not contain a fragment.`);return `${r.pathname}${r.search}`}o(Ye,"safeBrowserUrl");function Lt(e){if(!Array.isArray(e)||e.length===0||e.length>Ue)throw new Error(`Shader config scenes must contain 1...${Ue} entries.`);let t=new Set;return e.map((r,n)=>{if(!l(r)||typeof r.key!="string"||!Bt.test(r.key))throw new Error(`Shader config scene ${n} has an invalid key.`);if(t.has(r.key))throw new Error(`Shader config scene key "${r.key}" is duplicated.`);t.add(r.key);let i=r.parityFrames,s=r.maxDiffRatio;if(r.inputs!==void 0&&(!Array.isArray(r.inputs)||r.inputs.length===0||r.inputs.length>We))throw new Error(`Shader config scene "${r.key}" inputs must contain 1...${We} files.`);let a=r.inputs===void 0?void 0:r.inputs.map((c,f)=>Nt(c,`Shader config scene "${r.key}" input ${f}`));if(a!==void 0&&new Set(a).size!==a.length)throw new Error(`Shader config scene "${r.key}" inputs must be unique.`);if(r.runtimeMotion!==void 0&&typeof r.runtimeMotion!="boolean")throw new Error(`Shader config scene "${r.key}" runtimeMotion must be a boolean.`);if(r.backend!==void 0&&r.backend!=="webgpu"&&r.backend!=="webgl")throw new Error(`Shader config scene "${r.key}" backend must be "webgpu" or "webgl".`);return {key:r.key,url:Ye(r.url,`Shader config scene "${r.key}" URL`),...r.backend===void 0?{}:{backend:r.backend},requiresText:r.requiresText===true,...a===void 0?{}:{inputs:a},...i===void 0?{}:{parityFrames:L(i,`Shader config scene "${r.key}" parityFrames`,0,1e4,0)},...s===void 0?{}:{maxDiffRatio:Ke(s,`Shader config scene "${r.key}" maxDiffRatio`,.01)},...r.runtimeMotion===true?{runtimeMotion:true}:{}}})}o(Lt,"parseScenes");function we(e){if(!l(e)||e.schemaVersion!==void 0&&e.schemaVersion!==1)throw new Error("Shader config must use schemaVersion 1.");let t=e.viewport;if(t!==void 0&&!l(t))throw new Error("Shader config viewport must be an object.");let r=e.parity;if(r!==void 0&&!l(r))throw new Error("Shader config parity must be an object.");let n=e.bridge;if(n!==void 0&&!l(n))throw new Error("Shader config bridge must be an object.");let i=l(n)?n.deterministicModule:void 0;i!==void 0&&Ye(i,"Shader deterministic module");let s=e.readiness;if(s!==void 0&&!l(s))throw new Error("Shader config readiness must be an object.");let a=l(s)?s.selector:void 0;if(a!==void 0&&(typeof a!="string"||a.length===0||a.length>512||/[\u0000-\u001f\u007f]/u.test(a)))throw new Error("Shader readiness selector must be a bounded, non-empty CSS selector.");let c=l(s)?s.global:void 0;if(c!==void 0&&(typeof c!="string"||!Pt.test(c)))throw new Error("Shader readiness global must be a dot-separated JavaScript property path.");if(e.backend!==void 0&&e.backend!=="webgpu"&&e.backend!=="webgl"&&e.backend!=="both")throw new Error('Shader config backend must be "webgpu", "webgl", or "both".');let f=L(e.timeoutMs,"Shader timeoutMs",1e3,15*6e4,24e4);return {schemaVersion:1,backend:e.backend??"both",scenes:Lt(e.scenes),settleFrames:L(e.settleFrames,"Shader settleFrames",0,1e4,60),settleTimeoutMs:L(e.settleTimeoutMs,"Shader settleTimeoutMs",1e3,15*6e4,3e4),browserRelaunchScenes:L(e.browserRelaunchScenes,"Shader browserRelaunchScenes",1,64,8),timeoutMs:f,maxTimeoutMs:Math.max(f,L(e.maxTimeoutMs,"Shader maxTimeoutMs",1e3,15*6e4,f)),viewport:{width:L(l(t)?t.width:void 0,"Shader viewport width",64,8192,1024),height:L(l(t)?t.height:void 0,"Shader viewport height",64,8192,640)},parity:{frames:L(l(r)?r.frames:void 0,"Shader parity frames",0,1e4,90),channelTolerance:L(l(r)?r.channelTolerance:void 0,"Shader parity channelTolerance",0,255,8),maxDiffRatio:Ke(l(r)?r.maxDiffRatio:void 0,"Shader parity maxDiffRatio",.01)},bridge:{legacyLab:l(n)&&n.legacyLab===true,...typeof i=="string"?{deterministicModule:i}:{}},readiness:{...typeof a=="string"?{selector:a}:{},...typeof c=="string"?{global:c}:{}},publicDir:Ge(e.publicDir,"Shader publicDir","public"),allowLiveBuilds:e.allowLiveBuilds!==false}}o(we,"parseShaderToolConfig");async function Xe(e=process.cwd()){let t=b.resolve(e);for(;;){if(await C(b.join(t,Je))||await C(b.join(t,"three-blocks.json")))return realpath(t);let r=b.join(t,"package.json");if(await C(r)){let i=await B(t,r,$.packageJson,"Project package.json"),s;try{s=JSON.parse(i.data.toString("utf8"));}catch{throw new Error(`Project package.json is not valid JSON: ${r}.`)}if(l(s)&&[s.dependencies,s.devDependencies,s.peerDependencies,s.optionalDependencies].filter(l).some(f=>typeof f.three=="string"||typeof f["three-blocks"]=="string"||typeof f["@three-blocks/devtools"]=="string"))return realpath(t)}let n=b.dirname(t);if(n===t)throw new Error(`No Three Blocks shader project found from ${JSON.stringify(b.resolve(e))}; add Three.js to package.json or pass --root.`);t=n;}}o(Xe,"findShaderProjectRoot");async function ke(e){let t=await realpath(e),r=b.join(t,Je);if(await C(r)){let i=await B(t,r,$.metadata,"Shader configuration");return we(JSON.parse(i.data.toString("utf8")))}let n=b.join(t,"three-blocks.json");if(await C(n)){let i=ze(JSON.parse(await readFile(n,"utf8")));return we({schemaVersion:1,backend:"both",scenes:[{key:i.template,url:"/",requiresText:i.features.text}]})}return we(Ot)}o(ke,"loadShaderToolConfig");function Y(e,t="webgpu"){if(/^0\.185\./u.test(e))return t==="webgl"?THREE_WEBGL_R185_COMPATIBILITY:THREE_WEBGPU_R185_COMPATIBILITY;if(e===THREE_R186DEV_VERSION&&t==="webgpu")return THREE_WEBGPU_R186DEV_COMPATIBILITY;throw new Error(`Three.js ${e} is outside the supported shader compatibility contracts.`)}o(Y,"shaderCompatibilityForThree");var X="0.1.0";var me=64,Ut="timing.local.json",Wt="timing.json";var pe=4096,Jt=4096;function Re(e,t,r=8192){if(typeof e!="string"||e.length===0||e.length>r||/[\u0000\u007f]/u.test(e))throw new Error(`${t} must be a bounded non-empty string.`);return e}o(Re,"boundedString");function w(e,t,r=true){if(typeof e!="number"||!Number.isFinite(e)||e<0||r&&!Number.isSafeInteger(e))throw new Error(`${t} must be a non-negative ${r?"integer":"finite number"}.`);return e}o(w,"nonNegativeNumber");function qt(e){if(!l(e))throw new Error("Shader capture stats are missing.");let t={buildCalls:w(e.buildCalls,"capture stats.buildCalls"),renderBuilds:w(e.renderBuilds,"capture stats.renderBuilds"),computeBuilds:w(e.computeBuilds,"capture stats.computeBuilds"),registeredBuilds:w(e.registeredBuilds,"capture stats.registeredBuilds"),registeredRenderBuilds:w(e.registeredRenderBuilds,"capture stats.registeredRenderBuilds"),registeredComputeBuilds:w(e.registeredComputeBuilds,"capture stats.registeredComputeBuilds"),buildMs:w(e.buildMs,"capture stats.buildMs",false),syncBuildMs:w(e.syncBuildMs,"capture stats.syncBuildMs",false),asyncBuildElapsedMs:w(e.asyncBuildElapsedMs,"capture stats.asyncBuildElapsedMs",false),precompiledSetupMs:w(e.precompiledSetupMs,"capture stats.precompiledSetupMs",false),maxSyncBuildMs:w(e.maxSyncBuildMs??e.syncBuildMs,"capture stats.maxSyncBuildMs",false),maxPrecompiledSetupMs:w(e.maxPrecompiledSetupMs??e.precompiledSetupMs,"capture stats.maxPrecompiledSetupMs",false),hydrationMs:w(e.hydrationMs??0,"capture stats.hydrationMs",false),maxHydrationMs:w(e.maxHydrationMs??e.hydrationMs??0,"capture stats.maxHydrationMs",false),injected:w(e.injected,"capture stats.injected"),injectedRender:w(e.injectedRender,"capture stats.injectedRender"),injectedCompute:w(e.injectedCompute,"capture stats.injectedCompute"),missed:w(e.missed,"capture stats.missed"),missedRender:w(e.missedRender,"capture stats.missedRender"),missedCompute:w(e.missedCompute,"capture stats.missedCompute"),...Array.isArray(e.missedKeys)&&e.missedKeys.every(r=>typeof r=="string")?{missedKeys:e.missedKeys.slice(0,pe)}:{}};if(t.renderBuilds+t.computeBuilds!==t.buildCalls||t.registeredRenderBuilds+t.registeredComputeBuilds!==t.registeredBuilds||t.injectedRender+t.injectedCompute!==t.injected||t.missedRender+t.missedCompute!==t.missed||t.registeredBuilds>t.buildCalls||Math.abs(t.syncBuildMs+t.asyncBuildElapsedMs-t.buildMs)>.001||t.maxSyncBuildMs>t.syncBuildMs+.001||t.maxPrecompiledSetupMs>t.precompiledSetupMs+.001||t.maxHydrationMs>t.hydrationMs+.001)throw new Error("Shader capture stats totals are inconsistent.");return t}o(qt,"captureStats");function Gt(e){if(!Array.isArray(e)||e.length>pe)throw new Error("Shader capture skipped builds are invalid.");return e.map((t,r)=>{if(!l(t)||t.kind!=="render"&&t.kind!=="compute")throw new Error(`Shader capture skipped build ${r} is invalid.`);return {kind:t.kind,name:Re(t.name,`skipped build ${r} name`,512),reason:Re(t.reason,`skipped build ${r} reason`)}})}o(Gt,"skippedBuilds");function Kt(e){let t=0,r=0,n=0,i=0;for(let s of Object.values(e.entries)){let a=e.states[s];a!==void 0&&((a.vertex!==null||a.fragment!==null)&&t++,a.vertex!==null&&r++,a.fragment!==null&&n++,a.compute!==null&&i++);}return {render:t,vertex:r,fragment:n,compute:i}}o(Kt,"shaderCoverage");function Yt(e,t){if(!l(e))throw new Error("Shader capture payload must be an object.");if(e.scene!==t.scene)throw new Error(`Shader capture scene does not match "${t.scene}".`);if(e.protocolVersion!==2)throw new Error("Shader capture protocolVersion must be 2.");let r=t.backend??"webgpu",n=Y(t.runtime.three,r);if(e.compatibility!==n)throw new Error(`Shader capture compatibility must be "${n}".`);if(!l(e.entries))throw new Error("Shader capture entries must be an object.");if(typeof e.requiresSetup!="boolean")throw new Error("Shader capture requiresSetup must be boolean.");let i=Object.keys(e.entries).length;if(i>pe)throw new Error(`Shader capture must contain at most ${pe} entries.`);if(!Array.isArray(e.errors)||e.errors.length>Jt)throw new Error("Shader capture errors are invalid.");let s=e.errors.map((g,u)=>Re(g,`capture error ${u}`,64*1024));if(s.length>0)throw new Error(`Shader capture failed:
|
|
2
|
-
- ${
|
|
3
|
-
- `)}`);let
|
|
4
|
-
${e.map(
|
|
1
|
+
import {realpath,readFile,readdir,mkdir,unlink,lstat,open,rename,rm}from'fs/promises';import b from'path';import {parsePrecompiledManifest,SHADER_HYDRATION_SCHEMA_VERSION,SHADER_RECIPE_SCHEMA_VERSION,SHADER_ADDRESS_SCHEMA_VERSION,PRECOMPILED_MANIFEST_VERSION,threeShaderCompatibilityId}from'three-blocks/shaders';import {createHash,randomUUID}from'crypto';import {createRequire}from'module';var kt=Object.defineProperty;var a=(e,t)=>kt(e,"name",{value:t,configurable:true});var $=Object.freeze({metadata:1024*1024,receipt:2*1024*1024,manifest:32*1024*1024,semanticInput:8*1024*1024,semanticTotal:64*1024*1024,metrics:8*1024*1024,texture:128*1024*1024,packageJson:1024*1024});function Le(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"?e.code:void 0}a(Le,"errorCode");function I(e){return createHash("sha256").update(e).digest("hex")}a(I,"sha256");async function M(e){try{return await lstat(e),!0}catch(t){if(Le(t)==="ENOENT")return false;throw t}}a(M,"pathExists");function V(e,t){let r=b.relative(e,t);return r===""||!b.isAbsolute(r)&&r!==".."&&!r.startsWith(`..${b.sep}`)}a(V,"isWithin");function z(e){return JSON.stringify(e)}a(z,"displayPath");async function Fe(e,t,r){let n=await open(e,"r");try{let[s,i,o]=await Promise.all([lstat(e),n.stat(),realpath(e)]);if(s.isSymbolicLink())throw new Error(`${r} must not be a symbolic link: ${z(e)}.`);if(!i.isFile())throw new Error(`${r} must be a regular file: ${z(e)}.`);if(i.size>t)throw new Error(`${r} exceeds the ${t}-byte inspection limit: ${z(e)}.`);let d=await n.readFile();if(d.byteLength>t)throw new Error(`${r} grew beyond the ${t}-byte inspection limit while being read.`);return {path:o,data:d}}finally{await n.close();}}a(Fe,"readBoundedRegularFile");async function ce(e,t){let r=b.dirname(e);await mkdir(r,{recursive:true});try{if((await lstat(e)).isSymbolicLink())throw new Error(`Atomic write target must not be a symbolic link: ${z(e)}.`)}catch(i){if(Le(i)!=="ENOENT")throw i}let n=b.join(r,`.${b.basename(e)}.${process.pid}.${randomUUID()}.tmp`),s;try{s=await open(n,"wx",384),await s.writeFile(t),await s.sync(),await s.close(),s=void 0,await rename(n,e);}finally{await s?.close().catch(()=>{}),await rm(n,{force:true});}}a(ce,"writeAtomicRegularFile");async function ye(e,t,r){return Fe(e,t,r)}a(ye,"readExternalRegularFile");async function U(e,t,r){let n=b.resolve(e),s=b.resolve(t);if(!V(n,s))throw new Error(`${r} escapes its allowed directory.`);let i=await lstat(s);if(i.isSymbolicLink())throw new Error(`${r} must not be a symbolic link.`);if(!i.isDirectory())throw new Error(`${r} must be a directory.`);let[o,d]=await Promise.all([realpath(n),realpath(s)]);if(!V(o,d))throw new Error(`${r} resolves outside its allowed directory.`);return d}a(U,"canonicalDirectoryWithin");async function P(e,t,r,n){let s=b.resolve(e),i=b.resolve(t);if(!V(s,i)||s===i)throw new Error(`${n} escapes its allowed directory.`);let o=await Fe(i,r,n),d=await realpath(s);if(!V(d,o.path)||d===o.path)throw new Error(`${n} resolves outside its allowed directory.`);return o}a(P,"readRegularFileWithin");async function ve(e,t,r,n=8192){let i=[await U(e,t,"Inspected directory")],o=[],d=0;for(;i.length>0;){let f=i.shift();if(f===void 0)break;let m=(await readdir(f,{withFileTypes:true})).sort((h,c)=>h.name.localeCompare(c.name));for(let h of m){if(d+=1,d>n)throw new Error(`Inspected directory exceeds the ${n}-entry limit.`);let c=b.join(f,h.name);if(h.isSymbolicLink())throw new Error(`Inspected directory contains a symbolic link: ${z(b.relative(e,c))}.`);if(h.isDirectory()){i.push(await U(e,c,"Nested inspected directory"));continue}if(h.isFile()&&r(h.name))o.push(c);else if(r(h.name))throw new Error(`Semantic input is not a regular file: ${z(c)}.`)}}return o.sort()}a(ve,"listRegularFilesRecursively");var ue=/^[a-f0-9]{64}$/,Ct=/^[0-9A-Za-z][0-9A-Za-z.+_-]{0,127}$/,He=/^[a-z0-9][a-z0-9_-]{0,63}$/,Ve=/^[0-9A-Za-z][0-9A-Za-z._/-]{0,127}$/;function l(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}a(l,"isRecord");function W(e){return typeof e=="string"&&Ct.test(e)}a(W,"isSafeVersion");function Se(e){if(e.length===0||e.length>512||e.includes("\\")||/[\u0000-\u001f\u007f]/.test(e))return false;let t=e.split("/");return !e.startsWith("/")&&t.every(r=>r.length>0&&r!=="."&&r!=="..")}a(Se,"isSafeRelativePath");function ze(e){if(!l(e)||e.schemaVersion!==2)throw new Error("three-blocks.json must use schemaVersion 2.");if(typeof e.template!="string"||!He.test(e.template))throw new Error("three-blocks.json has an invalid default shader scene key.");if(!Array.isArray(e.layers)||!e.layers.every(t=>typeof t=="string"&&Ve.test(t))||new Set(e.layers).size!==e.layers.length)throw new Error("three-blocks.json has invalid layers.");if(e.generator!==void 0&&(!l(e.generator)||typeof e.generator.name!="string"||!Ve.test(e.generator.name)||!W(e.generator.version)))throw new Error("three-blocks.json has invalid generator metadata.");if(!l(e.runtime)||!W(e.runtime.three)||!W(e.runtime.threeBlocks))throw new Error("three-blocks.json has invalid runtime versions.");if(!l(e.features)||typeof e.features.text!="boolean")throw new Error("three-blocks.json has invalid feature metadata.");if(!l(e.protocol)||e.protocol.resultFile!==1)throw new Error("three-blocks.json has an unsupported protocol schema.");if(e.artifacts!==void 0){if(!l(e.artifacts)||typeof e.artifacts.shaders!="string"||!["fresh","pending"].includes(e.artifacts.shaders)||typeof e.artifacts.text!="string"||!["fresh","pending","not-applicable"].includes(e.artifacts.text))throw new Error("three-blocks.json has invalid artifact metadata.");if(e.features.text?e.artifacts.text==="not-applicable":e.artifacts.text!=="not-applicable")throw new Error("three-blocks.json text artifact state does not match the text capability.")}return {schemaVersion:2,template:e.template,layers:e.layers,...e.generator===void 0?{}:{generator:{name:e.generator.name,version:e.generator.version}},runtime:{three:e.runtime.three,threeBlocks:e.runtime.threeBlocks},features:{text:e.features.text},...e.artifacts===void 0?{}:{artifacts:{shaders:e.artifacts.shaders,text:e.artifacts.text}},protocol:{resultFile:1}}}a(ze,"parseProjectMetadata");function Mt(e){if(!l(e))throw new Error("Shader coverage is missing.");for(let t of ["render","vertex","fragment","compute"])if(typeof e[t]!="number"||!Number.isSafeInteger(e[t])||e[t]<0)throw new Error(`Shader coverage.${t} must be a non-negative integer.`);return e}a(Mt,"parseCoverage");function It(e,t){if(!l(e))throw new Error(`Shader receipt inputs for "${t}" are invalid.`);let r=Object.entries(e);if(r.length===0||r.length>4096)throw new Error(`Shader receipt inputs for "${t}" must contain between 1 and 4096 files.`);for(let[n,s]of r)if(!Se(n)||typeof s!="string"||!ue.test(s))throw new Error(`Shader receipt input for "${t}" is invalid.`)}a(It,"parseInputs");function le(e){if(!l(e)||e.schemaVersion!==2||!l(e.runtime)||!W(e.runtime.three)||!W(e.runtime.threeBlocks)||typeof e.runtime.threeBlocksShaderClosure!="string"||!ue.test(e.runtime.threeBlocksShaderClosure)||!l(e.scenes))throw new Error("Shader meta.json does not match receipt schema 2.");if(e.runtime.capture!==void 0&&(!l(e.runtime.capture)||typeof e.runtime.capture.userAgent!="string"||e.runtime.capture.userAgent.length>1024||typeof e.runtime.capture.adapter!="string"||e.runtime.capture.adapter.length>1024||!Array.isArray(e.runtime.capture.features)||e.runtime.capture.features.length>256||!e.runtime.capture.features.every(r=>typeof r=="string"&&r.length>0&&r.length<=128)))throw new Error("Shader meta.json has invalid browser capture provenance.");let t=Object.entries(e.scenes);if(t.length===0)throw new Error("Shader meta.json contains no scenes.");for(let[r,n]of t){let s=r.endsWith(".webgl")?"webgl":"webgpu",i=s==="webgl"?r.slice(0,-6):r;if(!He.test(i)||!l(n)||n.backend!==void 0&&n.backend!==s||typeof n.artifact!="string"||!Se(n.artifact)||!n.artifact.endsWith(`.${s}.ts`)||typeof n.artifactHash!="string"||!ue.test(n.artifactHash))throw new Error(`Shader receipt for "${r}" is invalid.`);if(n.asset===void 0!=(n.assetHash===void 0)||n.asset!==void 0&&(typeof n.asset!="string"||!Se(n.asset)||!n.asset.endsWith(".json")||typeof n.assetHash!="string"||!ue.test(n.assetHash)))throw new Error(`Shader static asset receipt for "${r}" is invalid.`);if(It(n.inputs,r),Mt(n.coverage),n.bytes!==void 0&&(!Number.isSafeInteger(n.bytes)||Number(n.bytes)<0))throw new Error(`Shader receipt byte count for "${r}" is invalid.`);if(n.skipped!==void 0&&(!l(n.skipped)||!Number.isSafeInteger(n.skipped.render)||Number(n.skipped.render)<0||!Number.isSafeInteger(n.skipped.compute)||Number(n.skipped.compute)<0))throw new Error(`Shader receipt skipped-build counts for "${r}" are invalid.`)}if(e.tool!==void 0&&(!l(e.tool)||e.tool.name!=="@three-blocks/devtools"||!W(e.tool.version)||typeof e.tool.compatibility!="string"||!Number.isSafeInteger(e.tool.transform)||!Number.isSafeInteger(e.tool.address)||!Number.isSafeInteger(e.tool.recipe)||!Number.isSafeInteger(e.tool.hydration)))throw new Error("Shader meta.json has invalid tool compatibility metadata.");if(l(e.tool)&&e.tool.compatibilities!==void 0&&(!l(e.tool.compatibilities)||Object.entries(e.tool.compatibilities).some(([r,n])=>r!=="webgpu"&&r!=="webgl"||typeof n!="string"||n.length===0)))throw new Error("Shader meta.json has invalid backend compatibility metadata.");return e}a(le,"parseShaderReceipt");var qe="three-blocks.shaders.json",Ee=".three-blocks/shaders";var _t=/^[a-z0-9][a-z0-9_-]{0,63}$/u,Ot=/^[A-Za-z_$][A-Za-z0-9_$]*(?:\.[A-Za-z_$][A-Za-z0-9_$]*)*$/u,Ue=64,We=64,Nt={schemaVersion:1,backend:"both",scenes:[{key:"default",url:"/"}]};function Je(e="both"){return e==="both"?["webgpu","webgl"]:[e]}a(Je,"shaderBackends");function q(e,t){return e.backend===void 0?t:t.filter(r=>r===e.backend)}a(q,"shaderSceneBackends");function G(e,t){return t==="webgpu"?e:`${e}.webgl`}a(G,"shaderReceiptKey");function Ke(e,t,r){if(e===void 0)return r;if(typeof e!="string"||e.length===0||e.length>512||b.isAbsolute(e)||/[\u0000-\u001f\u007f]/u.test(e))throw new Error(`${t} must be a bounded project-relative directory.`);let n=b.posix.normalize(e.replaceAll("\\","/")).replace(/\/+$/u,"");if(n==="."||n===".."||n.startsWith("../"))throw new Error(`${t} must stay inside the project.`);return n}a(Ke,"safeProjectDirectory");function Dt(e,t){let r=Ke(e,t,"");if(typeof e!="string"||e.endsWith("/"))throw new Error(`${t} must be a project-relative file.`);return r}a(Dt,"safeProjectFile");function L(e,t,r,n,s){if(e===void 0)return s;if(!Number.isSafeInteger(e)||Number(e)<r||Number(e)>n)throw new Error(`${t} must be an integer in ${r}...${n}.`);return Number(e)}a(L,"boundedInteger");function Ge(e,t,r){if(e===void 0)return r;if(typeof e!="number"||!Number.isFinite(e)||e<0||e>1)throw new Error(`${t} must be a finite ratio in 0...1.`);return e}a(Ge,"finiteRatio");function Xe(e,t){if(typeof e!="string"||e.length===0||e.length>2048||/[\u0000-\u001f\u007f]/u.test(e))throw new Error(`${t} must be a bounded project-relative URL.`);let r;try{r=new URL(e,"http://three-blocks.invalid/");}catch{throw new Error(`${t} is not a valid URL.`)}if(r.origin!=="http://three-blocks.invalid"||r.hash.length>0)throw new Error(`${t} must stay within the project and must not contain a fragment.`);return `${r.pathname}${r.search}`}a(Xe,"safeBrowserUrl");function Lt(e){if(!Array.isArray(e)||e.length===0||e.length>Ue)throw new Error(`Shader config scenes must contain 1...${Ue} entries.`);let t=new Set;return e.map((r,n)=>{if(!l(r)||typeof r.key!="string"||!_t.test(r.key))throw new Error(`Shader config scene ${n} has an invalid key.`);if(t.has(r.key))throw new Error(`Shader config scene key "${r.key}" is duplicated.`);t.add(r.key);let s=r.parityFrames,i=r.maxDiffRatio;if(r.inputs!==void 0&&(!Array.isArray(r.inputs)||r.inputs.length===0||r.inputs.length>We))throw new Error(`Shader config scene "${r.key}" inputs must contain 1...${We} files.`);let o=r.inputs===void 0?void 0:r.inputs.map((d,f)=>Dt(d,`Shader config scene "${r.key}" input ${f}`));if(o!==void 0&&new Set(o).size!==o.length)throw new Error(`Shader config scene "${r.key}" inputs must be unique.`);if(r.runtimeMotion!==void 0&&typeof r.runtimeMotion!="boolean")throw new Error(`Shader config scene "${r.key}" runtimeMotion must be a boolean.`);if(r.backend!==void 0&&r.backend!=="webgpu"&&r.backend!=="webgl")throw new Error(`Shader config scene "${r.key}" backend must be "webgpu" or "webgl".`);return {key:r.key,url:Xe(r.url,`Shader config scene "${r.key}" URL`),...r.backend===void 0?{}:{backend:r.backend},requiresText:r.requiresText===true,...o===void 0?{}:{inputs:o},...s===void 0?{}:{parityFrames:L(s,`Shader config scene "${r.key}" parityFrames`,0,1e4,0)},...i===void 0?{}:{maxDiffRatio:Ge(i,`Shader config scene "${r.key}" maxDiffRatio`,.01)},...r.runtimeMotion===true?{runtimeMotion:true}:{}}})}a(Lt,"parseScenes");function we(e){if(!l(e)||e.schemaVersion!==void 0&&e.schemaVersion!==1)throw new Error("Shader config must use schemaVersion 1.");let t=e.viewport;if(t!==void 0&&!l(t))throw new Error("Shader config viewport must be an object.");let r=e.parity;if(r!==void 0&&!l(r))throw new Error("Shader config parity must be an object.");let n=e.bridge;if(n!==void 0&&!l(n))throw new Error("Shader config bridge must be an object.");let s=l(n)?n.deterministicModule:void 0;s!==void 0&&Xe(s,"Shader deterministic module");let i=e.readiness;if(i!==void 0&&!l(i))throw new Error("Shader config readiness must be an object.");let o=l(i)?i.selector:void 0;if(o!==void 0&&(typeof o!="string"||o.length===0||o.length>512||/[\u0000-\u001f\u007f]/u.test(o)))throw new Error("Shader readiness selector must be a bounded, non-empty CSS selector.");let d=l(i)?i.global:void 0;if(d!==void 0&&(typeof d!="string"||!Ot.test(d)))throw new Error("Shader readiness global must be a dot-separated JavaScript property path.");if(e.backend!==void 0&&e.backend!=="webgpu"&&e.backend!=="webgl"&&e.backend!=="both")throw new Error('Shader config backend must be "webgpu", "webgl", or "both".');let f=L(e.timeoutMs,"Shader timeoutMs",1e3,15*6e4,24e4);return {schemaVersion:1,backend:e.backend??"both",scenes:Lt(e.scenes),settleFrames:L(e.settleFrames,"Shader settleFrames",0,1e4,60),settleTimeoutMs:L(e.settleTimeoutMs,"Shader settleTimeoutMs",1e3,15*6e4,3e4),browserRelaunchScenes:L(e.browserRelaunchScenes,"Shader browserRelaunchScenes",1,64,8),timeoutMs:f,maxTimeoutMs:Math.max(f,L(e.maxTimeoutMs,"Shader maxTimeoutMs",1e3,15*6e4,f)),viewport:{width:L(l(t)?t.width:void 0,"Shader viewport width",64,8192,1024),height:L(l(t)?t.height:void 0,"Shader viewport height",64,8192,640)},parity:{frames:L(l(r)?r.frames:void 0,"Shader parity frames",0,1e4,90),channelTolerance:L(l(r)?r.channelTolerance:void 0,"Shader parity channelTolerance",0,255,8),maxDiffRatio:Ge(l(r)?r.maxDiffRatio:void 0,"Shader parity maxDiffRatio",.01)},bridge:{legacyLab:l(n)&&n.legacyLab===true,...typeof s=="string"?{deterministicModule:s}:{}},readiness:{...typeof o=="string"?{selector:o}:{},...typeof d=="string"?{global:d}:{}},publicDir:Ke(e.publicDir,"Shader publicDir","public"),allowLiveBuilds:e.allowLiveBuilds!==false}}a(we,"parseShaderToolConfig");async function Ze(e=process.cwd()){let t=b.resolve(e);for(;;){if(await M(b.join(t,qe))||await M(b.join(t,"three-blocks.json")))return realpath(t);let r=b.join(t,"package.json");if(await M(r)){let s=await P(t,r,$.packageJson,"Project package.json"),i;try{i=JSON.parse(s.data.toString("utf8"));}catch{throw new Error(`Project package.json is not valid JSON: ${r}.`)}if(l(i)&&[i.dependencies,i.devDependencies,i.peerDependencies,i.optionalDependencies].filter(l).some(f=>typeof f.three=="string"||typeof f["three-blocks"]=="string"||typeof f["@three-blocks/devtools"]=="string"))return realpath(t)}let n=b.dirname(t);if(n===t)throw new Error(`No Three Blocks shader project found from ${JSON.stringify(b.resolve(e))}; add Three.js to package.json or pass --root.`);t=n;}}a(Ze,"findShaderProjectRoot");async function ke(e){let t=await realpath(e),r=b.join(t,qe);if(await M(r)){let s=await P(t,r,$.metadata,"Shader configuration");return we(JSON.parse(s.data.toString("utf8")))}let n=b.join(t,"three-blocks.json");if(await M(n)){let s=ze(JSON.parse(await readFile(n,"utf8"))),i=b.join(t,"src","scenes"),o=[];for(let d of (await readdir(i).catch(()=>[])).sort())await M(b.join(i,d,"scene.ts"))&&o.push(d);return we({schemaVersion:1,backend:"both",scenes:[{key:s.template,url:"/"},...o.map(d=>({key:d,url:`/?scene=${encodeURIComponent(d)}`}))].map(d=>({...d,requiresText:s.features.text}))})}return we(Nt)}a(ke,"loadShaderToolConfig");function X(e,t="webgpu"){let r=threeShaderCompatibilityId(e,t);if(r!==void 0)return r;throw new Error(`Three.js ${e} is outside the supported shader compatibility contracts.`)}a(X,"shaderCompatibilityForThree");var Z="0.1.0";var me=65,Ht="timing.local.json",zt="timing.json";var pe=4096,Ut=4096;function Wt(e){let t=a(s=>{let i=e[s];return typeof i=="number"&&Number.isSafeInteger(i)&&i>=0?i:void 0},"count"),r=t("stateChecked");if(r===void 0||r===0)return {};let n=e.stateDifferences;return {stateOracle:{checked:r,equivalent:t("stateEquivalent")??0,identical:t("stateIdentical")??0,recreated:t("stateRecreated")??0,differences:Array.isArray(n)?n.filter(s=>typeof s=="string").slice(0,40):[]}}}a(Wt,"parseShaderStateOracle");function Re(e,t,r=8192){if(typeof e!="string"||e.length===0||e.length>r||/[\u0000\u007f]/u.test(e))throw new Error(`${t} must be a bounded non-empty string.`);return e}a(Re,"boundedString");function w(e,t,r=true){if(typeof e!="number"||!Number.isFinite(e)||e<0||r&&!Number.isSafeInteger(e))throw new Error(`${t} must be a non-negative ${r?"integer":"finite number"}.`);return e}a(w,"nonNegativeNumber");function qt(e){if(!l(e))throw new Error("Shader capture stats are missing.");let t={buildCalls:w(e.buildCalls,"capture stats.buildCalls"),renderBuilds:w(e.renderBuilds,"capture stats.renderBuilds"),computeBuilds:w(e.computeBuilds,"capture stats.computeBuilds"),registeredBuilds:w(e.registeredBuilds,"capture stats.registeredBuilds"),registeredRenderBuilds:w(e.registeredRenderBuilds,"capture stats.registeredRenderBuilds"),registeredComputeBuilds:w(e.registeredComputeBuilds,"capture stats.registeredComputeBuilds"),buildMs:w(e.buildMs,"capture stats.buildMs",false),syncBuildMs:w(e.syncBuildMs,"capture stats.syncBuildMs",false),asyncBuildElapsedMs:w(e.asyncBuildElapsedMs,"capture stats.asyncBuildElapsedMs",false),precompiledSetupMs:w(e.precompiledSetupMs,"capture stats.precompiledSetupMs",false),maxSyncBuildMs:w(e.maxSyncBuildMs??e.syncBuildMs,"capture stats.maxSyncBuildMs",false),maxPrecompiledSetupMs:w(e.maxPrecompiledSetupMs??e.precompiledSetupMs,"capture stats.maxPrecompiledSetupMs",false),hydrationMs:w(e.hydrationMs??0,"capture stats.hydrationMs",false),maxHydrationMs:w(e.maxHydrationMs??e.hydrationMs??0,"capture stats.maxHydrationMs",false),injected:w(e.injected,"capture stats.injected"),injectedRender:w(e.injectedRender,"capture stats.injectedRender"),injectedCompute:w(e.injectedCompute,"capture stats.injectedCompute"),missed:w(e.missed,"capture stats.missed"),missedRender:w(e.missedRender,"capture stats.missedRender"),missedCompute:w(e.missedCompute,"capture stats.missedCompute"),...Array.isArray(e.missedKeys)&&e.missedKeys.every(r=>typeof r=="string")?{missedKeys:e.missedKeys.slice(0,pe)}:{},...Wt(e)};if(t.renderBuilds+t.computeBuilds!==t.buildCalls||t.registeredRenderBuilds+t.registeredComputeBuilds!==t.registeredBuilds||t.injectedRender+t.injectedCompute!==t.injected||t.missedRender+t.missedCompute!==t.missed||t.registeredBuilds>t.buildCalls||Math.abs(t.syncBuildMs+t.asyncBuildElapsedMs-t.buildMs)>.001||t.maxSyncBuildMs>t.syncBuildMs+.001||t.maxPrecompiledSetupMs>t.precompiledSetupMs+.001||t.maxHydrationMs>t.hydrationMs+.001)throw new Error("Shader capture stats totals are inconsistent.");return t}a(qt,"captureStats");function Jt(e){if(!Array.isArray(e)||e.length>pe)throw new Error("Shader capture skipped builds are invalid.");return e.map((t,r)=>{if(!l(t)||t.kind!=="render"&&t.kind!=="compute")throw new Error(`Shader capture skipped build ${r} is invalid.`);return {kind:t.kind,name:Re(t.name,`skipped build ${r} name`,512),reason:Re(t.reason,`skipped build ${r} reason`)}})}a(Jt,"skippedBuilds");function Kt(e){let t=0,r=0,n=0,s=0;for(let i of Object.values(e.entries)){let o=e.states[i];o!==void 0&&((o.vertex!==null||o.fragment!==null)&&t++,o.vertex!==null&&r++,o.fragment!==null&&n++,o.compute!==null&&s++);}return {render:t,vertex:r,fragment:n,compute:s}}a(Kt,"shaderCoverage");function Gt(e,t){if(!l(e))throw new Error("Shader capture payload must be an object.");if(e.scene!==t.scene)throw new Error(`Shader capture scene does not match "${t.scene}".`);if(e.protocolVersion!==2)throw new Error("Shader capture protocolVersion must be 2.");let r=t.backend??"webgpu",n=X(t.runtime.three,r);if(e.compatibility!==n)throw new Error(`Shader capture compatibility must be "${n}".`);if(!l(e.entries))throw new Error("Shader capture entries must be an object.");if(typeof e.requiresSetup!="boolean")throw new Error("Shader capture requiresSetup must be boolean.");let s=Object.keys(e.entries).length;if(s>pe)throw new Error(`Shader capture must contain at most ${pe} entries.`);if(!Array.isArray(e.errors)||e.errors.length>Ut)throw new Error("Shader capture errors are invalid.");let i=e.errors.map((g,u)=>Re(g,`capture error ${u}`,64*1024));if(i.length>0)throw new Error(`Shader capture failed:
|
|
2
|
+
- ${i.join(`
|
|
3
|
+
- `)}`);let o=Jt(e.skipped);if(s===0&&(r!=="webgl"||o.length===0))throw new Error("Shader capture must contain an entry unless WebGL explicitly skipped every live build.");let d=qt(e.stats),f=l(e.timing)?e.timing:void 0,m=f===void 0?void 0:Object.fromEntries(["launch","firstRequest","readiness","lastBuild","settled","posted"].flatMap(g=>{let u=f[g];if(u===void 0)return [];if(typeof u!="number"||!Number.isFinite(u)||u<0)throw new Error(`Shader capture timing.${g} is invalid.`);return [[g,u]]})),h;if(e.provenance!==void 0){if(!l(e.provenance)||typeof e.provenance.userAgent!="string"||e.provenance.userAgent.length>1024||typeof e.provenance.adapter!="string"||e.provenance.adapter.length>1024||!Array.isArray(e.provenance.features)||e.provenance.features.length>256||!e.provenance.features.every(g=>typeof g=="string"&&g.length<=128))throw new Error("Shader capture provenance is invalid.");h={userAgent:e.provenance.userAgent,adapter:e.provenance.adapter,features:[...new Set(e.provenance.features)].sort()};}let c=parsePrecompiledManifest({version:PRECOMPILED_MANIFEST_VERSION,scene:t.scene,three:t.runtime.three,threeBlocks:t.runtime.threeBlocks,runtime:{id:n,address:SHADER_ADDRESS_SCHEMA_VERSION,recipe:SHADER_RECIPE_SCHEMA_VERSION,hydration:SHADER_HYDRATION_SCHEMA_VERSION},...e.automatic===void 0?{}:{automatic:e.automatic},requiresSetup:e.requiresSetup,modules:e.modules,nodes:e.nodes,layouts:e.layouts,attributePlans:e.attributePlans,updatePlans:e.updatePlans,requirementPlans:e.requirementPlans,states:e.states,entries:e.entries,...e.fallbacks===void 0?{}:{fallbacks:e.fallbacks}}),p=Kt(c);if(d.registeredRenderBuilds<p.render||d.registeredComputeBuilds<p.compute)throw new Error("Shader capture did not live-build every distinct registered render/compute entry.");return {scene:t.scene,backend:r,manifest:c,skipped:o,stats:d,coverage:p,...m===void 0?{}:{timing:m},...h===void 0?{}:{provenance:h}}}a(Gt,"validateShaderCapture");function J(e,t=0){let r=" ".repeat(t),n=" ".repeat(t+1);if(Array.isArray(e))return e.length===0?"[]":e.every(i=>i===null||["number","string","boolean"].includes(typeof i))?JSON.stringify(e):`[
|
|
4
|
+
${e.map(i=>`${n}${J(i,t+1)}`).join(`,
|
|
5
5
|
`)}
|
|
6
|
-
${r}]`;if(e!==null&&typeof e=="object"){let
|
|
7
|
-
${
|
|
6
|
+
${r}]`;if(e!==null&&typeof e=="object"){let i=e,o=Object.keys(i).sort();return o.length===0?"{}":`{
|
|
7
|
+
${o.map(d=>{let f=i[d];return `${n}${JSON.stringify(d)}: ${J(f,t+1)}`}).join(`,
|
|
8
8
|
`)}
|
|
9
|
-
${r}}`}let
|
|
10
|
-
`)}
|
|
11
|
-
`;await ce(b.join(
|
|
12
|
-
`),f.push("meta.json"),{directory:t,receipt:h,files:f}}
|
|
9
|
+
${r}}`}let s=JSON.stringify(e);if(s===void 0)throw new Error("Shader artifact contains a non-serializable value.");return s}a(J,"stableStringify");function Xt(e){return ["// GENERATED FILE \u2014 do not edit by hand.","// Produced by @three-blocks/devtools.","import type { PrecompiledManifest } from 'three-blocks/shaders';","",`export default ${J(e)} satisfies PrecompiledManifest;`,""].join(`
|
|
10
|
+
`)}a(Xt,"serializeShaderManifest");function et(e,t){if(typeof e!="string"||e.length===0||e.length>256||/[\u0000-\u001f\u007f]/u.test(e))throw new Error(`${t} is invalid.`);return e}a(et,"timingLabel");function Zt(e){if(!l(e)||e.schemaVersion!==3||e.source!=="latest-local-capture"&&e.source!=="committed-capture"||typeof e.receiptHash!="string"||!/^[a-f0-9]{64}$/u.test(e.receiptHash)||typeof e.measuredAt!="string"||!Number.isFinite(Date.parse(e.measuredAt))||!l(e.scenes))throw new Error("Shader timing is invalid.");let t={};for(let[n,s]of Object.entries(e.scenes)){if(n.length===0||n.length>128||!l(s))throw new Error("Shader timing scene is invalid.");let i={builds:w(s.builds,`timing ${n}.builds`),setupMeasured:s.setupMeasured===true,liveBuildMs:w(s.liveBuildMs,`timing ${n}.liveBuildMs`,false),precompiledBuildMs:w(s.precompiledBuildMs,`timing ${n}.precompiledBuildMs`,false),avoidedBuildMs:w(s.avoidedBuildMs,`timing ${n}.avoidedBuildMs`,false),runs:w(s.runs,`timing ${n}.runs`),spreadMs:w(s.spreadMs,`timing ${n}.spreadMs`,false)};if(i.runs<1)throw new Error(`Shader timing runs are invalid for scene "${n}".`);if(Math.abs(i.avoidedBuildMs-Math.max(0,i.liveBuildMs-i.precompiledBuildMs))>.001)throw new Error(`Shader timing delta is inconsistent for scene "${n}".`);t[n]=i;}if(Object.keys(t).length===0)throw new Error("Shader timing contains no scenes.");let r={schemaVersion:3,receiptHash:e.receiptHash,measuredAt:e.measuredAt,scenes:t};return e.source==="latest-local-capture"?{...r,source:"latest-local-capture"}:{...r,source:"committed-capture",adapter:et(e.adapter,"Shader timing adapter"),platform:et(e.platform,"Shader timing platform")}}a(Zt,"parseShaderTiming");async function tt(e,t,r,n){let s=b.join(e,r);try{if(!await M(s))return;let i=await lstat(s);if(i.isSymbolicLink()||!i.isFile()||i.size>1024*1024)return;let o=Zt(JSON.parse(await readFile(s,"utf8")));return o.source===n&&o.receiptHash===I(t)?o:void 0}catch{return}}a(tt,"readShaderTimingFile");async function dt(e,t){return await tt(e,t,Ht,"latest-local-capture")??await tt(e,t,zt,"committed-capture")}a(dt,"readShaderTiming");async function rt(e){if(!await M(e)){await mkdir(e);return}let t=await lstat(e);if(t.isSymbolicLink()||!t.isDirectory())throw new Error(`Shader artifact path is not a real directory: ${e}.`)}a(rt,"assertDirectory");async function Yt(e){let t=b.resolve(e),r=b.join(t,".three-blocks");await rt(r);let n=b.join(r,"shaders");return await rt(n),n}a(Yt,"artifactRoot");async function Qt(e){let t=await Yt(e.root),r=e.backends??["webgpu"],n=Object.fromEntries(r.map(u=>[u,X(e.runtime.three,u)])),s=b.resolve(e.root),i=b.resolve(s,e.publicDirectory??"public");if(!V(s,i)||i===s)throw new Error("Shader public directory must stay inside the project root.");let o=b.join(i,"three-blocks","shaders");await mkdir(o,{recursive:true}),await U(s,o,"Shader static-asset directory");let d={},f=[];for(let u of [...e.scenes].sort((R,y)=>R.key.localeCompare(y.key))){let R=e.inputs.get(u.key);if(R===void 0)throw new Error(`Shader input matrix is missing scene "${u.key}".`);for(let y of q(u,r)){let k=G(u.key,y),x=e.captures.get(k);if(x===void 0){let S=e.previousReceipt?.scenes[k];if(S===void 0)continue;let D=await readFile(b.join(t,S.artifact));if(I(D)!==S.artifactHash)throw new Error(`Preserved shader artifact checksum differs for "${k}".`);if(S.asset!==void 0&&S.assetHash!==void 0){let j=await readFile(b.join(i,S.asset));if(I(j)!==S.assetHash)throw new Error(`Preserved static shader manifest checksum differs for "${k}".`)}d[k]={...S,backend:y,inputs:Object.fromEntries(Object.entries(R).sort(([j],[re])=>j.localeCompare(re)))},f.push(S.artifact),S.asset!==void 0&&f.push(b.relative(s,b.join(i,S.asset)).split(b.sep).join("/"));continue}if(x.scene!==u.key||x.backend!==y||x.manifest.scene!==u.key)throw new Error(`Capture matrix scene/backend "${k}" is inconsistent.`);let A=`${u.key}.${y}.ts`,N=Xt(x.manifest);await ce(b.join(t,A),N),f.push(A);let B=`three-blocks/shaders/${u.key}.${y}.json`,F=`${J(x.manifest)}
|
|
11
|
+
`;await ce(b.join(i,B),F),f.push(b.relative(s,b.join(i,B)).split(b.sep).join("/"));let v=x.skipped.filter(S=>S.kind==="render").length,T=x.skipped.length-v;d[k]={backend:y,artifact:A,artifactHash:I(N),asset:B,assetHash:I(F),inputs:Object.fromEntries(Object.entries(R).sort(([S],[D])=>S.localeCompare(D))),coverage:x.coverage,bytes:Buffer.byteLength(N),skipped:{render:v,compute:T}};}}let m=[...e.captures.values()].find(u=>u.provenance!==void 0)?.provenance??e.previousReceipt?.runtime.capture,h={schemaVersion:2,runtime:{...e.runtime,...m===void 0?{}:{capture:m}},tool:{name:"@three-blocks/devtools",version:Z,compatibility:n[r[0]??"webgpu"],compatibilities:n,transform:me,address:SHADER_ADDRESS_SCHEMA_VERSION,recipe:SHADER_RECIPE_SCHEMA_VERSION,hydration:SHADER_HYDRATION_SCHEMA_VERSION},scenes:d},c=new Set(f);for(let u of await readdir(t,{withFileTypes:true}))if(!(!/\.(?:webgpu|webgl)\.ts$/u.test(u.name)||c.has(u.name))){if(u.isSymbolicLink()||!u.isFile())throw new Error(`Orphan shader artifact is not a regular file: ${u.name}.`);await unlink(b.join(t,u.name));}let p=new Set(e.scenes.flatMap(u=>q(u,r).map(R=>`${u.key}.${R}.json`))),g=new Set(Object.values(e.previousReceipt?.scenes??{}).map(u=>u.asset===void 0?void 0:b.posix.basename(u.asset)).filter(u=>u!==void 0));try{let u=le(JSON.parse(await readFile(b.join(t,"meta.json"),"utf8")));for(let R of Object.values(u.scenes))R.asset!==void 0&&g.add(b.posix.basename(R.asset));}catch{}for(let u of await readdir(o,{withFileTypes:true}))if(!(!u.name.endsWith(".json")||p.has(u.name))&&g.has(u.name)){if(u.isSymbolicLink()||!u.isFile())throw new Error(`Orphan shader static asset is not a regular file: ${u.name}.`);await unlink(b.join(o,u.name));}return await ce(b.join(t,"meta.json"),`${J(h)}
|
|
12
|
+
`),f.push("meta.json"),{directory:t,receipt:h,files:f}}a(Qt,"writeShaderArtifacts");var Te=[".ts",".tsx",".mts",".cts",".js",".jsx",".mjs",".cjs",".wgsl",".glsl",".vert",".frag",".json",".css"],je=new Set(Te),xe=/^(?:three-blocks\.shaders\.json|(?:precompile|three-blocks\.shaders)\.config\.(?:cjs|cts|js|mjs|mts|ts))$/u,tr=/(?:^|\/)scene\.(?:cjs|cts|js|jsx|mjs|mts|ts|tsx)$/u,rr=/\b(?:export\s+)?(?:async\s+)?function\s+createScene\b|\bcreateScene\s*=\s*(?:async\s*)?\(/u,nr=/\b(?:[A-Za-z_$][\w$]*\.)*(?:shaders|shaderCache|sceneShaders)\s*\.\s*(?:material|pipeline|compute|container)\s*\(/u,ir=/\b(import|export)(?!\s*\()\s*(type\b\s*)?(?:[^"'();]*?\bfrom\s*)?["']([^"']+)["']/gu,sr=/\bimport\s*\(\s*["']([^"']+)["']\s*\)/gu,ar=/\b(?:import|export)(?!\s*\()\s*(?:[^"'();]*?\bfrom\s*)?["']([^"']+)["']|\bimport\s*\(\s*["']([^"']+)["']\s*\)/gu,or=/^[0-9A-Za-z][0-9A-Za-z.+_-]{0,127}$/u,$e=4096,dr="./shaders";function lt(e,t){let r=b.relative(e,t).split(b.sep).join("/");if(r.length===0||/[\u0000-\u001f\u007f]/u.test(r))throw new Error("Semantic input has an unsafe relative path.");return r}a(lt,"portableRelativePath");function Ae(e,t){try{return new TextDecoder("utf-8",{fatal:!0}).decode(e)}catch{throw new Error(`Shader-relevant source ${JSON.stringify(t)} is not valid UTF-8.`)}}a(Ae,"sourceText");function Me(e,t){let r="",n="code";for(let s=0;s<e.length;s++){let i=e[s]??"",o=e[s+1]??"";if(n==="code"){if(i==="/"&&o==="/"){r+=" ",n="line-comment",s++;continue}if(i==="/"&&o==="*"){r+=" ",n="block-comment",s++;continue}if(i==="'"||i==='"'||i==="`"){n=i==="'"?"single":i==='"'?"double":"template",r+=t?i:" ";continue}r+=i;continue}if(n==="line-comment"){i===`
|
|
13
13
|
`?(r+=`
|
|
14
|
-
`,n="code"):r+=" ";continue}if(n==="block-comment"){
|
|
14
|
+
`,n="code"):r+=" ";continue}if(n==="block-comment"){i==="*"&&o==="/"?(r+=" ",n="code",s++):r+=i===`
|
|
15
15
|
`?`
|
|
16
|
-
`:" ";continue}let
|
|
16
|
+
`:" ";continue}let d=n==="single"?"'":n==="double"?'"':"`";if(i==="\\"&&o.length>0){r+=t?`${i}${o}`:" ",s++;continue}r+=t?i:i===`
|
|
17
17
|
`?`
|
|
18
|
-
`:" ",
|
|
19
|
-
`);return I(c)}o(mr,"shaderRuntimeClosure");async function _e(e){let[t,r]=await Promise.all([ct(e,"three"),ct(e,"three-blocks")]);return {three:String(t.manifest.version),threeBlocks:String(r.manifest.version),threeBlocksShaderClosure:await mr(r.root,r.manifest)}}o(_e,"readInstalledShaderRuntime");var Z;async function gr(){Z===void 0&&(Z=(async()=>{let t=createRequire(b.join(process.cwd(),"package.json")).resolve("@three-blocks/devtools/browser/shader-capture"),r=b.resolve(b.dirname(t),"../..");return (await B(r,t,$.metadata,"Shader capture browser runtime")).data.toString("utf8")})());let e=Z;try{return await e}catch(t){throw Z===e&&(Z=void 0),t}}o(gr,"loadShaderCaptureRuntimeSource");var pt=4096,Sr=createRequire(import.meta.url),mt,E=new Proxy({},{get(e,t){return mt??=Sr("typescript"),Reflect.get(mt,t)}});function H(e){let t=e;for(;E.isParenthesizedExpression(t)||E.isAsExpression(t)||E.isSatisfiesExpression(t)||E.isNonNullExpression(t);)t=t.expression;return t}o(H,"unwrap");function wr(e){if(E.isIdentifier(e)||E.isStringLiteral(e)||E.isNumericLiteral(e))return e.text}o(wr,"propertyName");function Q(e,t){let r=new Map;for(let n of e.properties){if(!E.isPropertyAssignment(n))throw new Error(`${t} may contain only static property assignments.`);let i=wr(n.name);if(i===void 0||r.has(i))throw new Error(`${t} contains a computed or duplicate property.`);r.set(i,n.initializer);}return r}o(Q,"properties");function ee(e,t){if(e===void 0)throw new Error(`${t} is missing.`);let r=H(e);if(!E.isObjectLiteralExpression(r))throw new Error(`${t} must be a static object literal.`);return r}o(ee,"objectLiteral");function te(e,t){if(e===void 0)throw new Error(`${t} is missing.`);let r=H(e);if(!E.isStringLiteral(r)&&!E.isNoSubstitutionTemplateLiteral(r))throw new Error(`${t} must be a string literal.`);return r.text}o(te,"stringLiteral");function he(e,t){if(e===void 0)throw new Error(`${t} is missing.`);let r=H(e);if(!E.isNumericLiteral(r))throw new Error(`${t} must be a numeric literal.`);return Number(r.text)}o(he,"numericLiteral");function ht(e,t){if(e===void 0)throw new Error(`${t} is missing.`);let r=H(e);if(!E.isArrayLiteralExpression(r))throw new Error(`${t} must be a static array literal.`);return r.elements}o(ht,"arrayLiteral");function br(e,t){if(e===void 0)throw new Error(`${t} is missing.`);let r=H(e);if(r.kind===E.SyntaxKind.NullKeyword)return null;if(!E.isNumericLiteral(r))throw new Error(`${t} must be null or a numeric literal.`);return Number(r.text)}o(br,"numericOrNullLiteral");function Er(e){return e.parseDiagnostics??[]}o(Er,"parseDiagnostics");function gt(e,t,r,n){let i=E.createSourceFile(t,e,E.ScriptTarget.Latest,true,E.ScriptKind.TS),s=Er(i);if(s.length>0)throw new Error(`Shader manifest is not valid TypeScript: ${E.flattenDiagnosticMessageText(s[0]?.messageText??"parse error"," ")}`);let a=i.statements.filter(E.isExportAssignment).filter(y=>!y.isExportEquals);if(a.length!==1)throw new Error("Shader manifest must contain exactly one default export.");let c=Q(ee(a[0]?.expression,"Shader manifest default export"),"Shader manifest"),f=c.get("version");if(f===void 0||!E.isNumericLiteral(H(f))||Number(H(f).getText(i))!==3)throw new Error("Shader manifest version must be the numeric literal 3.");if(te(c.get("scene"),"Shader manifest scene")!==r)throw new Error(`Shader manifest scene does not match "${r}".`);let m=c.get("runtime"),d=(n?.compatibility??(m===void 0?"":te(Q(ee(m,"Shader manifest runtime"),"Shader manifest runtime").get("id"),"Shader manifest runtime id"))).startsWith("three-webgl-");if(n){if(te(c.get("three"),"Shader manifest Three.js version")!==n.three||te(c.get("threeBlocks"),"Shader manifest Three Blocks version")!==n.threeBlocks)throw new Error("Shader manifest runtime versions do not match its receipt.");let y=Q(ee(c.get("runtime"),"Shader manifest runtime"),"Shader manifest runtime");if(te(y.get("id"),"Shader manifest runtime id")!==n.compatibility||he(y.get("address"),"Shader manifest address schema")!==n.address||he(y.get("recipe"),"Shader manifest recipe schema")!==n.recipe||he(y.get("hydration"),"Shader manifest hydration schema")!==n.hydration)throw new Error("Shader manifest runtime compatibility schemas do not match its receipt.")}let p=Q(ee(c.get("entries"),"Shader manifest entries"),"Shader manifest entries");if(p.size===0&&!d||p.size>pt)throw new Error(`Shader manifest must contain ${d?"0":"1"}...${pt} entries.`);let g=ht(c.get("modules"),"Shader manifest modules").map((y,k)=>{let x=H(y);if(!E.isStringLiteral(x)&&!E.isNoSubstitutionTemplateLiteral(x))throw new Error(`Shader manifest module ${k} must be a shader string literal.`);if(x.text.length===0)throw new Error(`Shader manifest module ${k} is empty.`);return x.text}),u=ht(c.get("states"),"Shader manifest states").map((y,k)=>{let x=Q(ee(y,`Shader manifest state ${k}`),`Shader manifest state ${k}`),A=o((V,T)=>{let S=br(x.get(V),`Shader manifest state ${k} ${V}`);if(S===null)return false;let N=g[S];if(N===void 0||!d&&!N.includes(T))throw new Error(`Shader manifest state ${k} ${V} does not reference a ${T} module.`);return true},"moduleAt"),O=A("vertex","@vertex"),_=A("fragment","@fragment"),F=A("compute","@compute");if(F&&(O||_))throw new Error(`Shader manifest state ${k} mixes render and compute stages.`);if(!F&&!O&&!_)throw new Error(`Shader manifest state ${k} contains no shader stage.`);return {vertex:O,fragment:_,compute:F}}),R={render:0,vertex:0,fragment:0,compute:0};for(let[y,k]of p){if(y.length===0||/[\u0000-\u001f\u007f]/.test(y))throw new Error("Shader manifest contains an invalid entry key.");let x=he(k,`Shader manifest entry "${y}"`),A=u[x];if(A===void 0)throw new Error(`Shader manifest entry "${y}" references an absent state.`);(A.vertex||A.fragment)&&(R.render+=1),A.vertex&&(R.vertex+=1),A.fragment&&(R.fragment+=1),A.compute&&(R.compute+=1);}return R}o(gt,"inspectPrecompiledManifest");function kr(e,t){return e.render===t.render&&e.vertex===t.vertex&&e.fragment===t.fragment&&e.compute===t.compute}o(kr,"sameCoverage");function Rr(e){let t=e.some(n=>n.state==="invalid")?"invalid":e.some(n=>n.state==="missing")?"missing":e.some(n=>n.state==="stale")?"stale":"fresh",r=e.filter(n=>n.state===t);return {state:t,reason:t==="fresh"?`${e.length} configured shader scene${e.length===1?" is":"s are"} fresh.`:r.map(n=>`${n.scene} (${n.backend}): ${n.reason}`).join("; ")}}o(Rr,"classifyMatrix");function xr(e,t,r){let n=e.tool;if(!n)return "Shader receipt has no public tool compatibility metadata.";if((n.compatibilities?.[r]??n.compatibility)!==t)return "Shader receipt targets a different runtime compatibility contract.";if(n.transform!==me)return "Shader receipt uses a different provider transform version.";if(n.address!==SHADER_ADDRESS_SCHEMA_VERSION||n.recipe!==SHADER_RECIPE_SCHEMA_VERSION||n.hydration!==SHADER_HYDRATION_SCHEMA_VERSION)return "Shader receipt uses incompatible address, recipe, or hydration schemas."}o(xr,"exactToolCompatibility");function Tr(e,t){let r=Object.keys(t).filter(s=>Object.hasOwn(e,s)&&e[s]!==t[s]),n=Object.keys(t).filter(s=>!Object.hasOwn(e,s)),i=Object.keys(e).filter(s=>!Object.hasOwn(t,s));return {...r.length>0?{changedInputs:r}:{},...n.length>0?{addedInputs:n}:{},...i.length>0?{removedInputs:i}:{}}}o(Tr,"inputChanges");async function jr(e=process.cwd(),t,r){let n=await Xe(e),i=await ke(n),s=qe(r??i.backend),a=i.scenes.flatMap(m=>J(m,s).map(h=>({scene:m,backend:h,key:K(m.key,h)}))),c=b.join(n,Ee),f=o(()=>({schemaVersion:1,root:n,state:"missing",reason:`${Ee}/meta.json is absent.`,scenes:a.map(({scene:m,backend:h})=>({scene:m.key,backend:h,state:"missing",reason:"No committed shader receipt."}))}),"missing");if(!await C(c)||!await C(b.join(c,"meta.json")))return f();try{let m=await U(n,c,"Shader artifact directory"),h=await B(m,b.join(m,"meta.json"),$.receipt,"Shader receipt"),d=le(JSON.parse(h.data.toString("utf8"))),p=await dt(m,h.data),g=t??await _e(n),u=new Set(i.scenes.flatMap(T=>J(T,["webgpu","webgl"]).map(S=>K(T.key,S)))),y=Object.keys(d.scenes).filter(T=>!u.has(T));if(y.length>0)throw new Error(`Shader receipt contains unconfigured scenes: ${y.join(", ")}.`);let k=d.runtime.three!==g.three,x=d.runtime.threeBlocksShaderClosure!==g.threeBlocksShaderClosure,A=d.tool?.version!==X,O=b.join(n,i.publicDir??"public"),_=[];for(let{scene:T,backend:S,key:N}of a){let j=d.scenes[N];if(!j){_.push({scene:T.key,backend:S,state:"missing",reason:"Scene/backend is absent from the complete receipt matrix."});continue}let re=Y(g.three,S),Pe=xr(d,re,S);if(Pe)throw new Error(`${N}: ${Pe}`);let ne=await B(m,b.join(m,j.artifact),$.manifest,"Shader manifest");if(I(ne.data)!==j.artifactHash)throw new Error(`Shader artifact checksum differs for scene "${T.key}".`);if(j.asset!==void 0&&j.assetHash!==void 0){let Et=await B(O,b.join(O,j.asset),$.manifest,"Static shader manifest");if(I(Et.data)!==j.assetHash)throw new Error(`Static shader manifest checksum differs for scene "${T.key}".`)}if(j.bytes!==void 0&&j.bytes!==ne.data.byteLength)throw new Error(`Shader artifact byte count differs for scene "${T.key}".`);let ie=gt(ne.data.toString("utf8"),ne.path,T.key,{three:d.runtime.three,threeBlocks:d.runtime.threeBlocks,compatibility:re,address:SHADER_ADDRESS_SCHEMA_VERSION,recipe:SHADER_RECIPE_SCHEMA_VERSION,hydration:SHADER_HYDRATION_SCHEMA_VERSION});if(!kr(ie,j.coverage))throw new Error(`Shader coverage differs for scene "${T.key}".`);if(S==="webgpu"&&!i.allowLiveBuilds&&j.skipped&&j.skipped.render+j.skipped.compute>0)throw new Error(`Scene "${T.key}" contains skipped live builds but allowLiveBuilds is false.`);let bt=await Ie(n,T.inputs),se=Tr(j.inputs,bt),oe=(se.changedInputs?.length??0)+(se.addedInputs?.length??0)+(se.removedInputs?.length??0),Oe=k||x||A||oe>0,Ne=p?.scenes[N],ge=Ne===void 0||p===void 0?void 0:{...Ne,schemaVersion:p.schemaVersion,measuredAt:p.measuredAt,source:p.source,...p.source==="committed-capture"?{adapter:p.adapter,platform:p.platform}:{}};_.push({scene:T.key,backend:S,state:Oe?"stale":"fresh",reason:k?"Installed Three.js version differs from the receipt.":x?"Installed three-blocks/shaders runtime closure differs from the receipt.":A?`Receipt was generated by @three-blocks/devtools ${d.tool?.version??"unknown"}.`:oe>0?`${oe} semantic shader input${oe===1?"":"s"} changed.`:"Manifest, runtime, schemas, transform, and semantic inputs match.",coverage:ie,...!Oe&&ge!==void 0&&ge.builds===ie.render+ie.compute?{timing:ge}:{},...se});}let F=Rr(_),V=F.state==="fresh"&&p!==void 0&&_.every(T=>T.timing!==void 0)?p:void 0;return {schemaVersion:1,root:n,...F,scenes:_,runtime:g,receipt:d,...V===void 0?{}:{timing:V}}}catch(m){let h=m instanceof Error?m.message:String(m);return {schemaVersion:1,root:n,state:"invalid",reason:h,scenes:a.map(({scene:d,backend:p})=>({scene:d.key,backend:p,state:"invalid",reason:h}))}}}o(jr,"inspectShaderMatrix");export{me as SHADER_PROVIDER_TRANSFORM_VERSION,jr as inspectShaderMatrix,gr as loadShaderCaptureRuntimeSource,ke as loadShaderToolConfig,_e as readInstalledShaderRuntime,Ie as snapshotShaderInputs,q as stableStringify,Yt as validateShaderCapture,er as writeShaderArtifacts};
|
|
18
|
+
`:" ",i===d&&(n="code");}return r}a(Me,"lexicalSource");function cr(e){let t=new Set,r=Me(e,true);for(let n of r.matchAll(ir))n[2]===void 0&&n[3]!==void 0&&t.add(n[3]);for(let n of r.matchAll(sr))n[1]!==void 0&&t.add(n[1]);return [...t].sort()}a(cr,"importSpecifiers");function ur(e){let t=new Set;for(let r of Me(e,true).matchAll(ar)){let n=r[1]??r[2];n!==void 0&&t.add(n);}return [...t].sort()}a(ur,"runtimeSpecifiers");function ft(e){return (e.split(/[?#]/u,1)[0]??e).replaceAll("\\","/")}a(ft,"cleanSpecifier");function lr(e,t,r){let n=ft(t),s;if(n.startsWith("./")||n.startsWith("../"))s=b.posix.normalize(b.posix.join(b.posix.dirname(e),n));else if(n.startsWith("@/"))s=`src/${n.slice(2)}`;else if(n.startsWith("/src/"))s=n.slice(1);else return;if(s===".three-blocks"||s.startsWith(".three-blocks/"))return;let i=b.posix.extname(s).toLowerCase(),o=new Set([s]);if(i.length===0||!je.has(i)){for(let d of Te)o.add(`${s}${d}`);for(let d of Te)o.add(`${s}/index${d}`);}else if([".js",".mjs",".cjs",".jsx"].includes(i)){let d=s.slice(0,-i.length);for(let f of [".ts",".tsx",".mts",".cts"])o.add(`${d}${f}`);}return [...o].find(d=>r.has(d))}a(lr,"resolveProjectImport");function fr(e,t){let r=Me(t,false);return tr.test(e)||rr.test(r)||nr.test(r)}a(fr,"isShaderRoot");async function Ie(e,t){let r=await realpath(e);if(t!==void 0){let c={},p=0;for(let g of t){let u=await P(r,b.join(r,g),$.semanticInput,"Declared shader semantic input");if(p+=u.data.byteLength,p>$.semanticTotal)throw new Error("Declared shader semantic inputs exceed the total inspection size limit.");c[g]=I(u.data);}return c}let n=new Map,s=b.join(r,"src");if(await M(s))for(let c of await ve(r,s,p=>je.has(b.extname(p).toLowerCase()))){let p=await P(r,c,$.semanticInput,"Shader semantic input");n.set(lt(r,c),p.data);}for(let c of await readdir(r,{withFileTypes:true})){if(!c.isFile()||!xe.test(c.name)&&!je.has(b.extname(c.name).toLowerCase()))continue;let p=await P(r,b.join(r,c.name),$.semanticInput,xe.test(c.name)?"Shader configuration input":"Shader semantic input");n.set(c.name,p.data);}if(n.size>$e)throw new Error(`Shader input discovery exceeds the ${$e}-file limit.`);let i=new Set,o=new Map;for(let[c,p]of n){if(!c.includes("/")&&xe.test(c)&&i.add(c),!c.startsWith("src/"))continue;let g=Ae(p,c);o.set(c,g),fr(c,g)&&i.add(c);}if(i.size===0)throw new Error("No shader registration or scene source root was found.");let d=new Set,f=[...i].sort();for(;f.length>0;){let c=f.shift();if(c===void 0||d.has(c))continue;let p=n.get(c);if(p===void 0)continue;d.add(c);let g=o.get(c)??Ae(p,c);for(let u of cr(g)){let R=lr(c,u,n);R!==void 0&&!d.has(R)&&f.push(R);}f.sort();}let m=0,h={};for(let c of [...d].sort()){let p=n.get(c);if(p===void 0)throw new Error(`Shader input ${JSON.stringify(c)} disappeared during inspection.`);if(m+=p.byteLength,m>$.semanticTotal)throw new Error("Semantic shader inputs exceed the total inspection size limit.");h[c]=I(p);}return h}a(Ie,"snapshotShaderInputs");function Ce(e){if(typeof e=="string")return e;if(l(e))return Ce(e.import)??Ce(e.default)}a(Ce,"conditionalImportTarget");async function ct(e,t){let r=e;for(;;){let n=b.join(r,"node_modules",...t.split("/"),"package.json");if(await M(n)){let i=await ye(n,$.packageJson,`${t} package.json`),o=JSON.parse(i.data.toString("utf8"));if(!l(o)||o.name!==t||typeof o.version!="string"||!or.test(o.version))throw new Error(`Installed ${t} package metadata is invalid.`);return {root:b.dirname(i.path),manifest:o}}let s=b.dirname(r);if(s===r)break;r=s;}throw new Error(`Cannot verify the installed ${t} package.`)}a(ct,"findInstalledPackage");async function pr(e,t){if(!l(t.exports))throw new Error("Installed three-blocks package has no public exports map.");let r=Ce(t.exports[dr]);if(r===void 0||!r.startsWith("./"))throw new Error("Installed three-blocks shader export has no import target.");let n=await realpath(e),s=[b.resolve(n,r)],i=new Map,o=0;for(;s.length>0;){let f=s.shift();if(f===void 0)break;let m=await ye(f,$.semanticInput,"Three Blocks shader runtime module");if(!V(n,m.path)||m.path===n)throw new Error("Three Blocks shader runtime closure escapes its package.");let h=lt(n,m.path);if(i.has(h))continue;if(o+=m.data.byteLength,o>$.semanticTotal)throw new Error("Three Blocks shader runtime closure exceeds the inspection limit.");i.set(h,I(m.data));let c=Ae(m.data,h);for(let p of ur(c)){let g=ft(p);if(!g.startsWith("./")&&!g.startsWith("../"))continue;let u=b.resolve(b.dirname(m.path),g);if(!V(n,u))throw new Error("Three Blocks shader runtime import escapes its package.");s.push(u);}if(s.sort(),i.size+s.length>$e)throw new Error("Three Blocks shader runtime closure exceeds the file limit.")}let d=[...i].sort((f,m)=>f[0].localeCompare(m[0])).map(([f,m])=>`${f}\0${m}`).join(`
|
|
19
|
+
`);return I(d)}a(pr,"shaderRuntimeClosure");async function Be(e){let[t,r]=await Promise.all([ct(e,"three"),ct(e,"three-blocks")]);return {three:String(t.manifest.version),threeBlocks:String(r.manifest.version),threeBlocksShaderClosure:await pr(r.root,r.manifest)}}a(Be,"readInstalledShaderRuntime");var Y;async function hr(){Y===void 0&&(Y=(async()=>{let t=createRequire(b.join(process.cwd(),"package.json")).resolve("@three-blocks/devtools/browser/shader-capture"),r=b.resolve(b.dirname(t),"../..");return (await P(r,t,$.metadata,"Shader capture browser runtime")).data.toString("utf8")})());let e=Y;try{return await e}catch(t){throw Y===e&&(Y=void 0),t}}a(hr,"loadShaderCaptureRuntimeSource");var pt=4096,yr=createRequire(import.meta.url),mt,E=new Proxy({},{get(e,t){return mt??=yr("typescript"),Reflect.get(mt,t)}});function H(e){let t=e;for(;E.isParenthesizedExpression(t)||E.isAsExpression(t)||E.isSatisfiesExpression(t)||E.isNonNullExpression(t);)t=t.expression;return t}a(H,"unwrap");function Sr(e){if(E.isIdentifier(e)||E.isStringLiteral(e)||E.isNumericLiteral(e))return e.text}a(Sr,"propertyName");function Q(e,t){let r=new Map;for(let n of e.properties){if(!E.isPropertyAssignment(n))throw new Error(`${t} may contain only static property assignments.`);let s=Sr(n.name);if(s===void 0||r.has(s))throw new Error(`${t} contains a computed or duplicate property.`);r.set(s,n.initializer);}return r}a(Q,"properties");function ee(e,t){if(e===void 0)throw new Error(`${t} is missing.`);let r=H(e);if(!E.isObjectLiteralExpression(r))throw new Error(`${t} must be a static object literal.`);return r}a(ee,"objectLiteral");function te(e,t){if(e===void 0)throw new Error(`${t} is missing.`);let r=H(e);if(!E.isStringLiteral(r)&&!E.isNoSubstitutionTemplateLiteral(r))throw new Error(`${t} must be a string literal.`);return r.text}a(te,"stringLiteral");function he(e,t){if(e===void 0)throw new Error(`${t} is missing.`);let r=H(e);if(!E.isNumericLiteral(r))throw new Error(`${t} must be a numeric literal.`);return Number(r.text)}a(he,"numericLiteral");function ht(e,t){if(e===void 0)throw new Error(`${t} is missing.`);let r=H(e);if(!E.isArrayLiteralExpression(r))throw new Error(`${t} must be a static array literal.`);return r.elements}a(ht,"arrayLiteral");function wr(e,t){if(e===void 0)throw new Error(`${t} is missing.`);let r=H(e);if(r.kind===E.SyntaxKind.NullKeyword)return null;if(!E.isNumericLiteral(r))throw new Error(`${t} must be null or a numeric literal.`);return Number(r.text)}a(wr,"numericOrNullLiteral");function br(e){return e.parseDiagnostics??[]}a(br,"parseDiagnostics");function gt(e,t,r,n){let s=E.createSourceFile(t,e,E.ScriptTarget.Latest,true,E.ScriptKind.TS),i=br(s);if(i.length>0)throw new Error(`Shader manifest is not valid TypeScript: ${E.flattenDiagnosticMessageText(i[0]?.messageText??"parse error"," ")}`);let o=s.statements.filter(E.isExportAssignment).filter(y=>!y.isExportEquals);if(o.length!==1)throw new Error("Shader manifest must contain exactly one default export.");let d=Q(ee(o[0]?.expression,"Shader manifest default export"),"Shader manifest"),f=d.get("version");if(f===void 0||!E.isNumericLiteral(H(f))||Number(H(f).getText(s))!==3)throw new Error("Shader manifest version must be the numeric literal 3.");if(te(d.get("scene"),"Shader manifest scene")!==r)throw new Error(`Shader manifest scene does not match "${r}".`);let m=d.get("runtime"),c=(n?.compatibility??(m===void 0?"":te(Q(ee(m,"Shader manifest runtime"),"Shader manifest runtime").get("id"),"Shader manifest runtime id"))).startsWith("three-webgl-");if(n){if(te(d.get("three"),"Shader manifest Three.js version")!==n.three||te(d.get("threeBlocks"),"Shader manifest Three Blocks version")!==n.threeBlocks)throw new Error("Shader manifest runtime versions do not match its receipt.");let y=Q(ee(d.get("runtime"),"Shader manifest runtime"),"Shader manifest runtime");if(te(y.get("id"),"Shader manifest runtime id")!==n.compatibility||he(y.get("address"),"Shader manifest address schema")!==n.address||he(y.get("recipe"),"Shader manifest recipe schema")!==n.recipe||he(y.get("hydration"),"Shader manifest hydration schema")!==n.hydration)throw new Error("Shader manifest runtime compatibility schemas do not match its receipt.")}let p=Q(ee(d.get("entries"),"Shader manifest entries"),"Shader manifest entries");if(p.size===0&&!c||p.size>pt)throw new Error(`Shader manifest must contain ${c?"0":"1"}...${pt} entries.`);let g=ht(d.get("modules"),"Shader manifest modules").map((y,k)=>{let x=H(y);if(!E.isStringLiteral(x)&&!E.isNoSubstitutionTemplateLiteral(x))throw new Error(`Shader manifest module ${k} must be a shader string literal.`);if(x.text.length===0)throw new Error(`Shader manifest module ${k} is empty.`);return x.text}),u=ht(d.get("states"),"Shader manifest states").map((y,k)=>{let x=Q(ee(y,`Shader manifest state ${k}`),`Shader manifest state ${k}`),A=a((v,T)=>{let S=wr(x.get(v),`Shader manifest state ${k} ${v}`);if(S===null)return false;let D=g[S];if(D===void 0||!c&&!D.includes(T))throw new Error(`Shader manifest state ${k} ${v} does not reference a ${T} module.`);return true},"moduleAt"),N=A("vertex","@vertex"),B=A("fragment","@fragment"),F=A("compute","@compute");if(F&&(N||B))throw new Error(`Shader manifest state ${k} mixes render and compute stages.`);if(!F&&!N&&!B)throw new Error(`Shader manifest state ${k} contains no shader stage.`);return {vertex:N,fragment:B,compute:F}}),R={render:0,vertex:0,fragment:0,compute:0};for(let[y,k]of p){if(y.length===0||/[\u0000-\u001f\u007f]/.test(y))throw new Error("Shader manifest contains an invalid entry key.");let x=he(k,`Shader manifest entry "${y}"`),A=u[x];if(A===void 0)throw new Error(`Shader manifest entry "${y}" references an absent state.`);(A.vertex||A.fragment)&&(R.render+=1),A.vertex&&(R.vertex+=1),A.fragment&&(R.fragment+=1),A.compute&&(R.compute+=1);}return R}a(gt,"inspectPrecompiledManifest");function Er(e,t){return e.render===t.render&&e.vertex===t.vertex&&e.fragment===t.fragment&&e.compute===t.compute}a(Er,"sameCoverage");function kr(e){let t=e.some(n=>n.state==="invalid")?"invalid":e.some(n=>n.state==="missing")?"missing":e.some(n=>n.state==="stale")?"stale":"fresh",r=e.filter(n=>n.state===t);return {state:t,reason:t==="fresh"?`${e.length} configured shader scene${e.length===1?" is":"s are"} fresh.`:r.map(n=>`${n.scene} (${n.backend}): ${n.reason}`).join("; ")}}a(kr,"classifyMatrix");function Rr(e,t,r){let n=e.tool;if(!n)return "Shader receipt has no public tool compatibility metadata.";if((n.compatibilities?.[r]??n.compatibility)!==t)return "Shader receipt targets a different runtime compatibility contract.";if(n.transform!==me)return "Shader receipt uses a different provider transform version.";if(n.address!==SHADER_ADDRESS_SCHEMA_VERSION||n.recipe!==SHADER_RECIPE_SCHEMA_VERSION||n.hydration!==SHADER_HYDRATION_SCHEMA_VERSION)return "Shader receipt uses incompatible address, recipe, or hydration schemas."}a(Rr,"exactToolCompatibility");function xr(e,t){let r=Object.keys(t).filter(i=>Object.hasOwn(e,i)&&e[i]!==t[i]),n=Object.keys(t).filter(i=>!Object.hasOwn(e,i)),s=Object.keys(e).filter(i=>!Object.hasOwn(t,i));return {...r.length>0?{changedInputs:r}:{},...n.length>0?{addedInputs:n}:{},...s.length>0?{removedInputs:s}:{}}}a(xr,"inputChanges");async function Tr(e=process.cwd(),t,r){let n=await Ze(e),s=await ke(n),i=Je(r??s.backend),o=s.scenes.flatMap(m=>q(m,i).map(h=>({scene:m,backend:h,key:G(m.key,h)}))),d=b.join(n,Ee),f=a(()=>({schemaVersion:1,root:n,state:"missing",reason:`${Ee}/meta.json is absent.`,scenes:o.map(({scene:m,backend:h})=>({scene:m.key,backend:h,state:"missing",reason:"No committed shader receipt."}))}),"missing");if(!await M(d)||!await M(b.join(d,"meta.json")))return f();try{let m=await U(n,d,"Shader artifact directory"),h=await P(m,b.join(m,"meta.json"),$.receipt,"Shader receipt"),c=le(JSON.parse(h.data.toString("utf8"))),p=await dt(m,h.data),g=t??await Be(n),u=new Set(s.scenes.flatMap(T=>q(T,["webgpu","webgl"]).map(S=>G(T.key,S)))),y=Object.keys(c.scenes).filter(T=>!u.has(T));if(y.length>0)throw new Error(`Shader receipt contains unconfigured scenes: ${y.join(", ")}.`);let k=c.runtime.three!==g.three,x=c.runtime.threeBlocksShaderClosure!==g.threeBlocksShaderClosure,A=c.tool?.version!==Z,N=b.join(n,s.publicDir??"public"),B=[];for(let{scene:T,backend:S,key:D}of o){let j=c.scenes[D];if(!j){B.push({scene:T.key,backend:S,state:"missing",reason:"Scene/backend is absent from the complete receipt matrix."});continue}let re=X(g.three,S),_e=Rr(c,re,S);if(_e)throw new Error(`${D}: ${_e}`);let ne=await P(m,b.join(m,j.artifact),$.manifest,"Shader manifest");if(I(ne.data)!==j.artifactHash)throw new Error(`Shader artifact checksum differs for scene "${T.key}".`);if(j.asset!==void 0&&j.assetHash!==void 0){let Et=await P(N,b.join(N,j.asset),$.manifest,"Static shader manifest");if(I(Et.data)!==j.assetHash)throw new Error(`Static shader manifest checksum differs for scene "${T.key}".`)}if(j.bytes!==void 0&&j.bytes!==ne.data.byteLength)throw new Error(`Shader artifact byte count differs for scene "${T.key}".`);let ie=gt(ne.data.toString("utf8"),ne.path,T.key,{three:c.runtime.three,threeBlocks:c.runtime.threeBlocks,compatibility:re,address:SHADER_ADDRESS_SCHEMA_VERSION,recipe:SHADER_RECIPE_SCHEMA_VERSION,hydration:SHADER_HYDRATION_SCHEMA_VERSION});if(!Er(ie,j.coverage))throw new Error(`Shader coverage differs for scene "${T.key}".`);if(S==="webgpu"&&!s.allowLiveBuilds&&j.skipped&&j.skipped.render+j.skipped.compute>0)throw new Error(`Scene "${T.key}" contains skipped live builds but allowLiveBuilds is false.`);let bt=await Ie(n,T.inputs),se=xr(j.inputs,bt),ae=(se.changedInputs?.length??0)+(se.addedInputs?.length??0)+(se.removedInputs?.length??0),Oe=k||x||A||ae>0,Ne=p?.scenes[D],ge=Ne===void 0||p===void 0?void 0:{...Ne,schemaVersion:p.schemaVersion,measuredAt:p.measuredAt,source:p.source,...p.source==="committed-capture"?{adapter:p.adapter,platform:p.platform}:{}};B.push({scene:T.key,backend:S,state:Oe?"stale":"fresh",reason:k?"Installed Three.js version differs from the receipt.":x?"Installed three-blocks/shaders runtime closure differs from the receipt.":A?`Receipt was generated by @three-blocks/devtools ${c.tool?.version??"unknown"}.`:ae>0?`${ae} semantic shader input${ae===1?"":"s"} changed.`:"Manifest, runtime, schemas, transform, and semantic inputs match.",coverage:ie,...!Oe&&ge!==void 0&&ge.builds===ie.render+ie.compute?{timing:ge}:{},...se});}let F=kr(B),v=F.state==="fresh"&&p!==void 0&&B.every(T=>T.timing!==void 0)?p:void 0;return {schemaVersion:1,root:n,...F,scenes:B,runtime:g,receipt:c,...v===void 0?{}:{timing:v}}}catch(m){let h=m instanceof Error?m.message:String(m);return {schemaVersion:1,root:n,state:"invalid",reason:h,scenes:o.map(({scene:c,backend:p})=>({scene:c.key,backend:p,state:"invalid",reason:h}))}}}a(Tr,"inspectShaderMatrix");export{me as SHADER_PROVIDER_TRANSFORM_VERSION,Tr as inspectShaderMatrix,hr as loadShaderCaptureRuntimeSource,ke as loadShaderToolConfig,Be as readInstalledShaderRuntime,Ie as snapshotShaderInputs,J as stableStringify,Gt as validateShaderCapture,Qt as writeShaderArtifacts};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export{b as SHADER_ARTIFACT_DIRECTORY,c as SHADER_PARITY_DIRECTORY,a as SHADER_TOOL_CONFIG_FILE,l as ensureShaderToolConfig,i as findShaderProjectRoot,k as inferShaderCaptureTarget,j as loadShaderToolConfig,h as parseShaderToolConfig,d as shaderBackends,g as shaderReceiptKey,e as shaderSceneBackends,f as shaderScenePairs}from'./chunk-
|
|
1
|
+
export{b as SHADER_ARTIFACT_DIRECTORY,c as SHADER_PARITY_DIRECTORY,a as SHADER_TOOL_CONFIG_FILE,l as ensureShaderToolConfig,i as findShaderProjectRoot,k as inferShaderCaptureTarget,j as loadShaderToolConfig,h as parseShaderToolConfig,d as shaderBackends,g as shaderReceiptKey,e as shaderSceneBackends,f as shaderScenePairs}from'./chunk-75JSWKB4.js';import'./chunk-WNSGAV6N.js';import'./chunk-ECQE4D2U.js';import'./chunk-7X4DHW36.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{e as captureBuiltShaders,f as captureShaders,d as inspectShaderMatrix,h as testShaders,g as withStateOracle}from'./chunk-HIS44NIG.js';import'./chunk-EX34XRLW.js';import'./chunk-ZG3LO3VB.js';import'./chunk-WWBW6MPB.js';import'./chunk-UDMY6S4M.js';import'./chunk-TK566QET.js';import'./chunk-75JSWKB4.js';import'./chunk-WNSGAV6N.js';import'./chunk-ECQE4D2U.js';import'./chunk-7X4DHW36.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{b as RUNTIME_STATUS_RECEIPT_MAX_BYTES,a as RUNTIME_STATUS_RECEIPT_PATH,c as RUNTIME_STATUS_RECOVERY,e as findProjectRoot,i as formatShaderMatrixStatus,j as formatStatus,k as formatThreeBlocksStatus,f as inspectProject,g as inspectThreeBlocksStatus,d as parseRuntimeStatusReceipt,h as threeBlocksStatusIsFresh}from'./chunk-2SGYUV6P.js';export{c as readInstalledShaderRuntime,b as snapshotShaderInputs}from'./chunk-HIS44NIG.js';import'./chunk-CMMYXGQ3.js';import'./chunk-MIJXPQPM.js';import'./chunk-EX34XRLW.js';import'./chunk-ZG3LO3VB.js';import'./chunk-WWBW6MPB.js';import'./chunk-UDMY6S4M.js';import'./chunk-TK566QET.js';import'./chunk-75JSWKB4.js';import'./chunk-WNSGAV6N.js';import'./chunk-ECQE4D2U.js';import'./chunk-7X4DHW36.js';
|