@three-blocks/devtools 11.0.0 → 11.1.0-alpha.395.g9b8ccb48a515

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.
Files changed (77) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/NOTICE +26 -0
  3. package/README.md +117 -170
  4. package/dist/asset-optimize-YJGWKD4Y.js +1 -0
  5. package/dist/asset-transforms-ZVZ4RD4L.js +11 -0
  6. package/dist/browser/shader-capture.js +2 -2
  7. package/dist/browser-smoke-4MYMHKWB.js +1 -0
  8. package/dist/chunk-4SVF5BRM.js +2 -0
  9. package/dist/chunk-7X4DHW36.js +1 -0
  10. package/dist/chunk-BBODS5RH.js +5 -0
  11. package/dist/{chunk-IILE5RBI.js → chunk-CMMYXGQ3.js} +1 -2
  12. package/dist/chunk-DCLDEPPB.js +253 -0
  13. package/dist/{chunk-5L2VS3BN.js → chunk-ECQE4D2U.js} +1 -2
  14. package/dist/chunk-IWQV456Z.js +3 -0
  15. package/dist/chunk-LSH64HEU.js +80 -0
  16. package/dist/{chunk-X5OFYHIY.js → chunk-MIJXPQPM.js} +2 -3
  17. package/dist/chunk-NDIPQLTU.js +16 -0
  18. package/dist/{chunk-NPLE7PPF.js → chunk-NJITVI23.js} +1 -2
  19. package/dist/chunk-O5FU2ASS.js +16 -0
  20. package/dist/chunk-QQKHDH26.js +1 -0
  21. package/dist/chunk-S5LI2C2H.js +5 -0
  22. package/dist/chunk-SBUKHO24.js +1 -0
  23. package/dist/chunk-TK566QET.js +1 -0
  24. package/dist/{chunk-65VEJRRT.js → chunk-WNSGAV6N.js} +1 -2
  25. package/dist/chunk-ZG3LO3VB.js +1 -0
  26. package/dist/{chunk-UDUICSME.js → chunk-ZTHZE36A.js} +1 -1
  27. package/dist/cli.d.ts +1 -0
  28. package/dist/cli.js +26 -26
  29. package/dist/environment-bake-ON5I27N7.js +1 -0
  30. package/dist/index.d.ts +24 -12
  31. package/dist/index.js +1 -279
  32. package/dist/{shader-autowire-SPE5DM2X.js → shader-autowire-D2EOG6GF.js} +1 -2
  33. package/dist/shader-browser-6ICBHK3S.js +1 -0
  34. package/dist/shader-capture-server.d.ts +1 -1
  35. package/dist/shader-capture-server.js +1 -1
  36. package/dist/{shader-config-EOFU5D3Y.js → shader-config-AKZEKIRB.js} +1 -2
  37. package/dist/{shader-parity-QXJWR6OZ.js → shader-parity-7DEPQEDI.js} +1 -1
  38. package/dist/{shader-project-runner-S2AID2RJ.js → shader-project-runner-NV4GKHDX.js} +1 -2
  39. package/dist/shader-watch-JBUA4LP5.js +1 -0
  40. package/dist/shader-workflow-5EHHR32D.js +1 -0
  41. package/dist/status-GDVSLQWV.js +1 -0
  42. package/dist/text-atlas-YYWV7S6F.js +1 -0
  43. package/dist/transform.cjs +1 -1
  44. package/dist/transform.js +1 -1
  45. package/dist/webpack-loader.cjs +1 -1
  46. package/dist/webpack-loader.js +1 -1
  47. package/node/index.d.mts +70 -0
  48. package/node/index.mjs +407 -0
  49. package/node/ipc.mjs +31 -0
  50. package/node/layout.mjs +546 -0
  51. package/node/loader.mjs +103 -0
  52. package/node/media.mjs +454 -0
  53. package/node/recording.mjs +67 -0
  54. package/node/worker.mjs +1314 -0
  55. package/package.json +27 -11
  56. package/dist/asset-optimize-GG72JCOX.js +0 -6
  57. package/dist/browser-smoke-KFF7XV7F.js +0 -254
  58. package/dist/chunk-45AVKQQK.js +0 -80
  59. package/dist/chunk-5FT6AZD6.js +0 -82
  60. package/dist/chunk-7N6TU4JG.js +0 -17
  61. package/dist/chunk-EI7MMDWY.js +0 -1
  62. package/dist/chunk-HOZDD6PW.js +0 -2
  63. package/dist/chunk-LKXY5YU2.js +0 -17
  64. package/dist/chunk-MIUIIPS4.js +0 -1
  65. package/dist/chunk-NF4RFSUJ.js +0 -18
  66. package/dist/chunk-QJFPNM6W.js +0 -2
  67. package/dist/chunk-ZT6T2W4B.js +0 -2
  68. package/dist/chunk-ZZLAZ7GJ.js +0 -6
  69. package/dist/environment-bake-BGMGFAVK.js +0 -4
  70. package/dist/shader-browser-H5CB2ZQX.js +0 -2
  71. package/dist/shader-browser-UXXR6QI2.js +0 -1
  72. package/dist/shader-parity-XPKQQK26.js +0 -2
  73. package/dist/shader-watch-EORZ2SEC.js +0 -2
  74. package/dist/shader-workflow-7NQFDQI5.js +0 -2
  75. package/dist/status-PTBB4SW2.js +0 -2
  76. package/dist/text-atlas-UORTLOQJ.js +0 -2
  77. /package/dist/{chunk-TRHSN2DJ.cjs → chunk-LMLJIVNY.cjs} +0 -0
@@ -0,0 +1,253 @@
1
+ import {b as b$1,a as a$2}from'./chunk-BBODS5RH.js';import {b}from'./chunk-ZG3LO3VB.js';import {a as a$1}from'./chunk-WNSGAV6N.js';import {j,a as a$3,c}from'./chunk-ECQE4D2U.js';import {a}from'./chunk-7X4DHW36.js';import {launchNodeRenderer}from'@three-blocks/devtools/node';import {randomUUID}from'crypto';import {mkdir,realpath,writeFile,rename,rm}from'fs/promises';import F from'path';import {PNG}from'pngjs';var ce="virtual:three-blocks-devtools/browser-smoke",be=`\0${ce}`,De=`/@id/__x00__${ce}`,Se=9e4;async function Re(){return {vite:await import('vite')}}a(Re,"loadBrowserSmokeTools");function V(e,t,o,r,s){let a=e??s;if(!Number.isSafeInteger(a)||a<o||a>r)throw new Error(`${t} must be an integer in ${o}...${r}.`);return a}a(V,"boundedInteger");function Be(e,t,o,r,s){let a=e??s;if(!Number.isFinite(a)||a<o||a>r)throw new Error(`${t} must be a finite number in ${o}...${r}.`);return a}a(Be,"boundedRatio");function Ee(e){let t=e??"/";if(t.length===0||t.length>2048||/[\u0000-\u001f\u007f]/u.test(t))throw new Error("Browser smoke route must be a bounded project URL.");let o=new URL(t,"http://three-blocks.invalid/");if(o.origin!=="http://three-blocks.invalid"||o.hash.length>0)throw new Error("Browser smoke route must stay within the project and have no fragment.");return `${o.pathname}${o.search}`}a(Ee,"safeRoute");function N(e,t){return e[t]===true}a(N,"booleanField");function $(e,t){if(!a$1(e)||!a$1(e.value))return {source:"missing",backend:"unknown",worker:false,workerReady:false,assetsReady:false,compileEnd:false,textEnabled:t,textReady:!t,firstFrame:false};let o=e.value,r=e.source==="public";if(r&&o.protocolVersion!==1)return {source:"public",backend:"unknown",worker:false,workerReady:false,assetsReady:false,compileEnd:false,textEnabled:t,textReady:!t,firstFrame:false};let s=a$1(o.readiness)?o.readiness:o,a=o.worker,u=r&&a$1(a)?a.offscreenCanvas===true&&a.visible===true:a===true;return {source:r?"public":"legacy",backend:r&&a$1(a)?a.offscreenCanvas===true?"OffscreenCanvas":"MainThread":a===true?"OffscreenCanvas":"unknown",worker:u,workerReady:N(s,"workerReady"),assetsReady:N(s,"assetsReady")||N(s,"loadEnd"),compileEnd:N(s,"compileEnd"),textEnabled:t,textReady:!t||N(s,"textReady"),firstFrame:N(s,"firstFrame")}}a($,"parseBrowserSmokeLifecycle");function ae(e){let t=PNG.sync.read(e),o=Math.floor(t.width*.25),r=Math.floor(t.width*.75),s=Math.floor(t.height*.25),a=Math.floor(t.height*.75),u=0,i=0;for(let y=s;y<a;y+=2)for(let f=o;f<r;f+=2){let b=(y*t.width+f)*4,l=t.data[b],n=t.data[b+1],m=t.data[b+2];l===void 0||n===void 0||m===void 0||(u+=Math.max(l,n,m),i+=1);}return i===0?0:u/i}a(ae,"screenshotLuminance");function ze(){return `
2
+ import * as THREE from 'three/webgpu';
3
+ import { createAssetLoaderRegistry, createAssetManager, createThreeAssetAdapters, defineAssets } from 'three-blocks/assets';
4
+ import { SceneHotReloader } from 'three-blocks/hmr';
5
+ import { createShaderCache } from 'three-blocks/shaders';
6
+ import { createStatsWorker } from 'three-blocks/stats';
7
+ import { threeBlocksBuildReceipt, threeBlocksConfig, loadThreeBlocksMeshoptDecoder } from 'three-blocks/vite/config';
8
+
9
+ const root = globalThis;
10
+ const hmr = root.__threeBlocksSmokeProbe ??= { before: 0, after: 0 };
11
+ if ( import.meta.hot ) {
12
+ import.meta.hot.on( 'vite:beforeUpdate', () => { hmr.before += 1; } );
13
+ import.meta.hot.on( 'vite:afterUpdate', () => { hmr.after += 1; } );
14
+ import.meta.hot.accept();
15
+ }
16
+
17
+ async function externalCodec( name, config, pathKey ) {
18
+ if ( config === false ) return { name, state: 'disabled', routes: [], decoded: false, evidence: 'delivery', blocker: null, error: null };
19
+ const routes = [];
20
+ try {
21
+ for ( const file of config.files ) {
22
+ const route = config[ pathKey ] + file;
23
+ const response = await fetch( new URL( route, location.origin ), { cache: 'no-store' } );
24
+ const body = await response.arrayBuffer();
25
+ if ( ! response.ok ) throw new Error( route + ' returned HTTP ' + response.status );
26
+ if ( body.byteLength === 0 ) throw new Error( route + ' returned an empty body' );
27
+ routes.push( { route: new URL( route, location.origin ).pathname, bytes: body.byteLength, contentType: response.headers.get( 'content-type' ) ?? '' } );
28
+ }
29
+ return {
30
+ name,
31
+ state: 'ready',
32
+ routes,
33
+ decoded: false,
34
+ evidence: 'delivery',
35
+ blocker: null,
36
+ error: null,
37
+ };
38
+ } catch ( error ) {
39
+ return { name, state: 'error', routes, decoded: false, evidence: 'delivery', blocker: null, error: error instanceof Error ? error.message : String( error ) };
40
+ }
41
+ }
42
+
43
+ async function meshoptCodec() {
44
+ if ( threeBlocksConfig.codecs.meshopt === false ) return { name: 'meshopt', state: 'disabled', routes: [], decoded: false, evidence: 'decoder-ready', blocker: null, error: null };
45
+ try {
46
+ const decoder = await loadThreeBlocksMeshoptDecoder();
47
+ await decoder.ready;
48
+ if ( decoder.supported !== true ) throw new Error( 'Meshopt decoder reports supported=false' );
49
+ return {
50
+ name: 'meshopt',
51
+ state: 'ready',
52
+ routes: [],
53
+ decoded: false,
54
+ evidence: 'decoder-ready',
55
+ blocker: null,
56
+ error: null,
57
+ };
58
+ } catch ( error ) {
59
+ return { name: 'meshopt', state: 'error', routes: [], decoded: false, evidence: 'decoder-ready', blocker: null, error: error instanceof Error ? error.message : String( error ) };
60
+ }
61
+ }
62
+
63
+ async function decodeCodecFixtures() {
64
+ const fixtureRoot = '/__three-blocks-codec-fixtures';
65
+ const available = await fetch( fixtureRoot + '/Box.gltf', { cache: 'no-store' } ).then( async response => {
66
+ if ( ! response.ok ) return false;
67
+ try {
68
+ const value = JSON.parse( await response.text() );
69
+ return Array.isArray( value?.extensionsUsed ) && value.extensionsUsed.includes( 'KHR_draco_mesh_compression' );
70
+ } catch {
71
+ return false;
72
+ }
73
+ }, () => false );
74
+ if ( ! available ) return null;
75
+ const canvas = document.createElement( 'canvas' );
76
+ canvas.width = 4;
77
+ canvas.height = 4;
78
+ const renderer = new THREE.WebGPURenderer( { canvas, antialias: false } );
79
+ let runtime;
80
+ let manager;
81
+ try {
82
+ await renderer.init();
83
+ runtime = createThreeAssetAdapters( {
84
+ renderer,
85
+ codecs: threeBlocksConfig.codecs,
86
+ loadMeshopt: loadThreeBlocksMeshoptDecoder,
87
+ } );
88
+ manager = createAssetManager( runtime.registry );
89
+ const load = async ( name, definition, validate ) => {
90
+ try {
91
+ const lease = await manager.lease( defineAssets( { fixture: definition } ) );
92
+ try {
93
+ if ( ! validate( lease.assets.fixture ) ) throw new Error( name + ' returned the wrong decoded object.' );
94
+ return { ok: true, error: null };
95
+ } finally {
96
+ lease.release();
97
+ }
98
+ } catch ( error ) {
99
+ return { ok: false, error: error instanceof Error ? error.message : String( error ) };
100
+ }
101
+ };
102
+ return {
103
+ draco: await load( 'Draco', { type: 'gltf', url: fixtureRoot + '/Box.gltf' }, value => value?.scene?.isObject3D === true ),
104
+ meshopt: await load( 'Meshopt', { type: 'gltf', url: fixtureRoot + '/Meshopt.gltf' }, value => value?.scene?.isObject3D === true ),
105
+ ktx2: await load( 'KTX2', { type: 'ktx2', url: fixtureRoot + '/geist.msdf.ktx2' }, value => value?.isTexture === true ),
106
+ };
107
+ } finally {
108
+ await manager?.shutdown();
109
+ await runtime?.dispose();
110
+ renderer.dispose();
111
+ }
112
+ }
113
+
114
+ async function proveHotRuntime() {
115
+ const sharedAsset = { id: 'shared-browser-smoke-asset' };
116
+ let disposedAssets = 0;
117
+ const registry = createAssetLoaderRegistry( {
118
+ json: {
119
+ type: 'json',
120
+ load: async () => sharedAsset,
121
+ dispose: () => { disposedAssets += 1; },
122
+ },
123
+ } );
124
+ const manager = createAssetManager( registry );
125
+ const manifest = { shared: { type: 'json', url: '/__three-blocks-smoke-shared.json' } };
126
+ const createScene = async ( name ) => {
127
+ const scope = manager.createScope();
128
+ const assets = await scope.load( manifest );
129
+ return {
130
+ name,
131
+ asset: assets.shared,
132
+ hot: { state: 0 },
133
+ dispose() { scope.dispose(); },
134
+ };
135
+ };
136
+ const first = await createScene( 'first' );
137
+ first.hot.state = 37;
138
+ let now = 0;
139
+ const pushed = [];
140
+ const profiler = {
141
+ init() {}, begin() {}, end() {}, update() {}, dispose() {},
142
+ getData: () => ( { fps: 60, cpu: 1, gpu: 2, gpuCompute: 3 } ),
143
+ };
144
+ const stats = createStatsWorker( {
145
+ sampleRate: 4,
146
+ now: () => now,
147
+ publish: ( value ) => pushed.push( value ),
148
+ createProfiler: async () => profiler,
149
+ } );
150
+ await stats.init( {} );
151
+ stats.beginFrame();
152
+ stats.endFrame();
153
+ const stableStats = stats;
154
+ const reloader = new SceneHotReloader( first, {
155
+ context: { manager, stats },
156
+ compile: ( candidate ) => {
157
+ if ( candidate.name === 'failed' ) throw new Error( 'intentional browser-smoke compile failure' );
158
+ },
159
+ } );
160
+ const replaced = await reloader.replace( () => createScene( 'second' ) );
161
+ now = 300;
162
+ stats.beginFrame();
163
+ stats.endFrame();
164
+ const cacheAfterCommit = manager.cacheSnapshot();
165
+ const committed = reloader.current;
166
+ let rollbackPhase = null;
167
+ try {
168
+ await reloader.replace( () => createScene( 'failed' ) );
169
+ } catch ( error ) {
170
+ rollbackPhase = error && typeof error === 'object' ? error.phase : null;
171
+ }
172
+ const cacheAfterRollback = manager.cacheSnapshot();
173
+ const shaderCache = createShaderCache( 'browser-smoke' );
174
+ const firstMaterial = {};
175
+ const firstRegistration = shaderCache.forScene( 'browser-smoke' ).material( 'browser-smoke/material', firstMaterial );
176
+ const nextMaterial = {};
177
+ const nextRegistration = shaderCache.forScene( 'browser-smoke', { replaceExisting: true } )
178
+ .material( 'browser-smoke/material', nextMaterial );
179
+ firstRegistration.dispose();
180
+ const invalidation = shaderCache.invalidationFor( 'browser-smoke/material', 'browser-smoke' );
181
+ const shaderReplacementActive = shaderCache.registration( 'browser-smoke/material', 'browser-smoke' )?.target === nextMaterial;
182
+ nextRegistration.dispose();
183
+ const result = {
184
+ sceneIdentityReplaced: replaced.previous === first && replaced.current === committed && committed !== first,
185
+ stateRestored: committed.hot.state === 37,
186
+ assetIdentityPreserved: first.asset === committed.asset && committed.asset === sharedAsset,
187
+ assetReferencesPreserved: cacheAfterCommit.length === 1 && cacheAfterCommit[ 0 ]?.references === 1 && disposedAssets === 0,
188
+ statsIdentityPreserved: stats === stableStats,
189
+ statsSequenceAdvanced: pushed.length === 2 && pushed[ 0 ]?.sequence === 0 && pushed[ 1 ]?.sequence === 1,
190
+ shaderInvalidated: shaderReplacementActive && invalidation?.key === 'browser-smoke/material' && /replaced during HMR/.test( invalidation.reason ),
191
+ rollbackPreserved: rollbackPhase === 'compile' && reloader.current === committed && cacheAfterRollback.length === 1 && cacheAfterRollback[ 0 ]?.references === 1,
192
+ };
193
+ committed.dispose();
194
+ stats.dispose();
195
+ await manager.shutdown();
196
+ return result;
197
+ }
198
+
199
+ export async function probe() {
200
+ const codecs = [
201
+ await externalCodec( 'draco', threeBlocksConfig.codecs.draco, 'decoderPath' ),
202
+ await externalCodec( 'ktx2', threeBlocksConfig.codecs.ktx2, 'transcoderPath' ),
203
+ await meshoptCodec(),
204
+ ];
205
+ const decoded = await decodeCodecFixtures();
206
+ if ( decoded ) {
207
+ for ( const codec of codecs ) {
208
+ const result = decoded[ codec.name ];
209
+ if ( result?.ok ) {
210
+ codec.decoded = true;
211
+ codec.evidence = 'asset-manager-decoded';
212
+ codec.blocker = null;
213
+ } else if ( result ) {
214
+ codec.state = 'error';
215
+ codec.error = result.error;
216
+ }
217
+ }
218
+ }
219
+ return {
220
+ textEnabled: threeBlocksConfig.text.enabled,
221
+ receipt: threeBlocksBuildReceipt,
222
+ hmrEvidence: await proveHotRuntime(),
223
+ codecs,
224
+ };
225
+ }
226
+ `}a(ze,"browserProbeSource");function Ke(){return {name:"three-blocks:browser-smoke-probe",enforce:"post",resolveId(e){return e===ce?be:void 0},load(e){return e===be?ze():void 0}}}a(Ke,"browserProbePlugin");function _e(e){let t={console:[],page:[]};return e.on("console",o=>{o.type()!=="error"||b(o.text())||t.console.push(o.text());}),e.on("pageerror",o=>{b(o.message)||t.page.push(o.message);}),t}a(_e,"collectPageErrors");async function H(e){return e.evaluate(()=>{let t=globalThis,o=t.__threeBlocksSmoke;if(o!==void 0)return {source:"public",value:o};let r=t.__threeBlocksBrowserTools;if(r&&typeof r=="object"){let s=Reflect.get(r,"smoke");if(s!==void 0)return {source:"public",value:s}}return {source:t.__threeBlocks===void 0?"missing":"legacy",value:t.__threeBlocks??null}})}a(H,"readBridge");async function Je(e){return e.evaluate(()=>{let t=globalThis,o=t.document.querySelector("[data-tb-fatal-code]"),r=o?.getAttribute("data-tb-fatal-code")??"",s=(o?.title||o?.textContent||"")?.replace(/^three-blocks — error:\s*/u,"").replace(/^Uncaught(?:\s+Error)?:\s*/u,"").trim()??"";return {fatalVisible:o!==null&&/^[a-z][a-z0-9-]{0,63}$/u.test(r)&&t.getComputedStyle(o).display!=="none"&&t.getComputedStyle(o).visibility!=="hidden",code:r.length>0?r:null,detail:s.length>0?s:null}})}a(Je,"readCompatibilityFailure");async function ke(e){return e.evaluate(()=>{let t=globalThis,o=t.__threeBlocksTextFallbackProbe?.states,r=Array.isArray(o)?o.filter(i=>typeof i=="string").slice(0,32):[],s=r.indexOf("fallback"),a=r.lastIndexOf("ready"),u=[...t.document.querySelectorAll("[data-canvas-text]")];return {states:r,fallbackObserved:s>=0,recovered:s>=0&&a>s,visibleElements:u.filter(i=>i.getAttribute("data-canvas-text-fallback")!=="false").length,totalElements:u.length}})}a(ke,"readTextFallbackEvidence");async function X(e){return e.evaluate(()=>{let t=globalThis,o=t.__threeBlocksSmoke?.diagnostics?.shaderMode;return {snapshots:Math.max(0,Number(t.__threeBlocksSmoke?.stats?.snapshots)||0),textures:Math.max(0,Number(t.__threeBlocksSmoke?.stats?.textures)||0),shaderMode:o==="precompiled"||o==="live"?o:null,mainPanels:t.document.querySelector("[data-three-blocks-stats-mode]")!==null}})}a(X,"readBrowserRuntimeObservation");async function Xe(e,t){let o=Buffer.from(`${JSON.stringify(t,null,2)}
227
+ `,"utf8");if(o.byteLength>b$1)throw new Error(`Runtime status receipt exceeds ${b$1} bytes.`);let r=F.join(e,...a$2.split("/")),s=F.dirname(r);await mkdir(s,{recursive:true});let a=await realpath(s),u=F.relative(e,a);if(u.startsWith("..")||F.isAbsolute(u))throw new Error("Runtime status receipt directory escapes the project root.");let i=F.join(a,`.status.${process.pid}.${randomUUID()}.tmp`);try{await writeFile(i,o,{flag:"wx",mode:384}),await rename(i,r);}finally{await rm(i,{force:true});}}a(Xe,"writeRuntimeStatusReceipt");async function Y(e,t,o){await e.waitForFunction(r=>{let s=globalThis,a=s.__threeBlocksSmoke,u=a!==void 0;if(a===void 0){let l=s.__threeBlocksBrowserTools;l&&typeof l=="object"&&(a=Reflect.get(l,"smoke")),u=a!==void 0;}if(a===void 0&&(a=s.__threeBlocks),!a||typeof a!="object")return false;let i=a;if(u&&i.protocolVersion!==1)return false;let y=i.readiness&&typeof i.readiness=="object"?i.readiness:i,f=i.worker;return (u&&f&&typeof f=="object"?Reflect.get(f,"offscreenCanvas")===true&&Reflect.get(f,"visible")===true:f===true)&&y.workerReady===true&&(y.assetsReady===true||y.loadEnd===true)&&y.compileEnd===true&&y.firstFrame===true&&(!r||y.textReady===true)},t,{timeout:o});}a(Y,"waitForLifecycle");async function ge(e,t){await e.waitForFunction(()=>{let r=[...globalThis.document.querySelectorAll("[data-canvas-text]")];return r.length>0&&r.every(s=>s.getAttribute("data-canvas-text-fallback")==="true")},void 0,{timeout:Math.min(t,3e4)});}a(ge,"waitForTextFallback");async function se(e,t,o){await t();let r=250,s=performance.now()+Math.min(o,5e3),a$1=performance.now(),u=a(()=>{a$1=performance.now();},"navigated");e.on("framenavigated",u);try{for(;performance.now()-a$1<r;){if(performance.now()>=s)throw new Error("Timed out waiting for startup navigation to settle.");await e.waitForTimeout(25);}}finally{e.off("framenavigated",u);}await t();}a(se,"waitForStableReadiness");async function ve(e,t){return await e(),t()}a(ve,"readAfterInitialReadiness");function Ye(e,t,o){if(!a$1(e)||typeof e.route!="string"||!e.route.startsWith("/")||e.route.length>2048||!Number.isSafeInteger(e.bytes)||Number(e.bytes)<=0||typeof e.contentType!="string"||e.contentType.length>256)throw new Error(`Browser codec ${t} route ${o} is invalid.`);let r=e.route.endsWith(".wasm")?"application/wasm":"javascript";if(!e.contentType.includes(r))throw new Error(`Browser codec route ${e.route} returned unexpected content-type ${JSON.stringify(e.contentType)}.`);return {route:e.route,bytes:Number(e.bytes),contentType:e.contentType}}a(Ye,"parseCodecRoute");function G(e,t,o){if(typeof e!="string"||!t.includes(e))throw new Error(`${o} is invalid.`);return e}a(G,"literal");function ne(e,t){if(!Number.isSafeInteger(e)||Number(e)<0)throw new Error(`${t} is invalid.`);return Number(e)}a(ne,"nonnegativeInteger");function Ze(e){if(!a$1(e)||e.schemaVersion!==2||!a$1(e.renderer)||!a$1(e.assets)||!a$1(e.shaders)||!a$1(e.stats)||typeof e.output!="string"||e.output.length===0||e.output.length>2048||typeof e.threeVersion!="string"||e.threeVersion.length===0||e.threeVersion.length>128)throw new Error("Browser build receipt is invalid.");if(e.renderer.owner!=="worker"||e.renderer.api!=="WebGPU"||e.renderer.fallback!=="WebGL")throw new Error("Browser build receipt does not declare the worker-owned WebGPU/WebGL renderer contract.");let t=e.text;if(t!==void 0&&(!a$1(t)||!["ready","generating","fallback","missing","invalid"].includes(String(t.state))))throw new Error("Browser build receipt text state is invalid.");return {schemaVersion:2,renderer:{owner:"worker",api:"WebGPU",fallback:"WebGL"},assets:{draco:G(e.assets.draco,["ready","disabled"],"Browser build receipt Draco state"),ktx2:G(e.assets.ktx2,["ready","disabled"],"Browser build receipt KTX2 state"),meshopt:G(e.assets.meshopt,["lazy","disabled"],"Browser build receipt Meshopt state")},shaders:{state:G(e.shaders.state,["fresh","stale","invalid","missing"],"Browser build receipt shader state"),mode:G(e.shaders.mode,["precompiled","live"],"Browser build receipt shader mode"),pipelines:ne(e.shaders.pipelines,"Browser build receipt shader pipeline count")},...t===void 0?{}:{text:{state:G(t.state,["ready","generating","fallback","missing","invalid"],"Browser build receipt text state"),atlases:ne(t.atlases,"Browser build receipt text atlas count"),glyphs:ne(t.glyphs,"Browser build receipt text glyph count")}},stats:{enabled:e.stats.enabled===true,production:e.stats.production===true},output:e.output,threeVersion:e.threeVersion}}a(Ze,"parseBuildReceipt");var le=Object.freeze({sceneIdentityReplaced:false,stateRestored:false,assetIdentityPreserved:false,assetReferencesPreserved:false,statsIdentityPreserved:false,statsSequenceAdvanced:false,shaderInvalidated:false,rollbackPreserved:false}),K=Object.freeze({requested:false,appIdentityStable:false,contentIdentityStable:false,canvasReplaced:false,workerIdentityChanged:false,generationAdvanced:false,restartCountAdvanced:false,stateReplayed:false,readinessRestored:false,shaderModeStable:false,statsSnapshotsAdvanced:false,statsTextureTransferred:false,statsTextureStopped:false,error:null}),Qe=Object.freeze(["three-blocks/assets","three-blocks/hmr","three-blocks/runtime","three-blocks/shaders","three-blocks/stats","three-blocks/text","three-blocks/worker"]);function er(e){if(!a$1(e))throw new Error("Browser HMR evidence is invalid.");let t={...le};for(let o of Object.keys(t)){if(e[o]!==true)throw new Error(`Browser HMR evidence ${o} did not pass.`);t[o]=true;}return t}a(er,"parseHmrEvidence");function rr(e){if(!a$1(e)||typeof e.textEnabled!="boolean"||!Array.isArray(e.codecs)||e.codecs.length!==3)throw new Error("Browser codec probe returned an invalid payload.");let t=["draco","ktx2","meshopt"],o=e.codecs.map((r,s)=>{let a=t[s];if(a===void 0||!a$1(r)||r.name!==a||!["ready","disabled","error"].includes(String(r.state))||!Array.isArray(r.routes)||r.error!==null&&typeof r.error!="string")throw new Error(`Browser codec probe entry ${s} is invalid.`);let u=r.state,i=r.routes.map((f,b)=>Ye(f,a,b)),y=G(r.evidence,["delivery","decoder-ready","text-atlas-decoded","asset-manager-decoded"],`Browser codec ${a} evidence`);if(typeof r.decoded!="boolean"||r.blocker!==null&&typeof r.blocker!="string")throw new Error(`Browser codec ${a} decode evidence is invalid.`);if(u==="ready"&&a!=="meshopt"&&i.length===0)throw new Error(`Browser codec ${a} exposed no routes.`);if(u==="error"&&(typeof r.error!="string"||r.error.length===0||r.error.length>8192))throw new Error(`Browser codec ${a} has an invalid error.`);return {name:a,state:u,routes:i,decoded:r.decoded,evidence:y,blocker:typeof r.blocker=="string"?r.blocker:null,error:typeof r.error=="string"?r.error:null}});return {textEnabled:e.textEnabled,codecs:o,receipt:Ze(e.receipt),hmrEvidence:er(e.hmrEvidence)}}a(rr,"parseCodecProbe");async function tr(e){let t=await e.evaluate(async o=>{let r=await import(o);if(typeof r.probe!="function")throw new Error("Browser smoke probe module has no probe() export.");return await r.probe()},De);return rr(t)}a(tr,"probeCodecs");function or(e){return e instanceof Error&&/execution context was destroyed|most likely because of a navigation/iu.test(e.message)}a(or,"isNavigationRace");async function nr(e,t,o){for(let r=0;r<3;r++)try{return await tr(e)}catch(s){if(!or(s)||r===2)throw s;await se(e,t,o);}throw new Error("Browser codec probe did not complete.")}a(nr,"probeCodecsAfterNavigation");async function ie(e){return e.evaluate(()=>{let t=globalThis,o=0;for(let r of t.document.querySelectorAll("canvas")){if(r.width<=0||r.height<=0)continue;let s=null;try{s=r.getContext("2d");}catch{continue}if(s)try{let a=s.getImageData(0,0,r.width,r.height).data,u=0,i=0;for(let y=0;y+2<a.length;y+=4)u+=Math.max(a[y]??0,a[y+1]??0,a[y+2]??0),i+=1;i>0&&(o=Math.max(o,u/i));}catch{}}return o})}a(ie,"panelLuminance");function ar(e){return e.split(F.sep).join("/")}a(ar,"portablePath");async function sr(e){return e.evaluate(()=>{let o=globalThis.__threeBlocksSmokeProbe;if(!o||typeof o!="object")return 0;let r=Reflect.get(o,"after");return typeof r=="number"&&Number.isSafeInteger(r)?r:0})}a(sr,"hmrEventCount");async function lr(e,t,o,r,s,a,u){if(r===void 0)return {requested:false,module:null,dispatched:false,acknowledged:false,lifecycleStable:true,sourceUnchanged:true,evidenceSource:"public-runtime-node-probe",evidence:u,restart:K,error:null};let i=ar(r),y=false,f=false,b=false,l=false;try{let n=await j(o,F.join(o,r),a$3.semanticInput,"HMR scene module"),m=c(n.data),c$1=e.moduleGraph.getModulesByFile(n.path);if(!c$1||c$1.size===0)throw new Error(`HMR scene module ${JSON.stringify(i)} is not in Vite's module graph.`);let p=await sr(t);e.watcher.emit("change",n.path),y=!0,await t.waitForFunction(U=>{let T=globalThis.__threeBlocksSmokeProbe;return !!(T&&typeof T=="object"&&Number(Reflect.get(T,"after"))>U)},p,{timeout:Math.min(s,3e4)}),f=!0,await Y(t,a,Math.min(s,3e4)),b=!0;let P=await j(o,n.path,a$3.semanticInput,"HMR scene module");if(l=c(P.data)===m,!l)throw new Error("HMR scene source changed during the smoke run.");return {requested:!0,module:i,dispatched:y,acknowledged:f,lifecycleStable:b,sourceUnchanged:l,evidenceSource:"public-runtime-node-probe",evidence:u,restart:K,error:null}}catch(n){return {requested:true,module:i,dispatched:y,acknowledged:f,lifecycleStable:b,sourceUnchanged:l,evidenceSource:"public-runtime-node-probe",evidence:u,restart:K,error:n instanceof Error?n.message:String(n)}}}a(lr,"exerciseHmr");async function ir(e,t,o,r){let s="stats-baseline";try{let a=await e.evaluate(()=>{let l=globalThis;return new URL(l.location.href).searchParams.get("tbStats")==="1"});a&&(s="stats-query-boot",await e.waitForFunction(()=>globalThis.__threeBlocksSmoke?.stats?.panelVisible===!0,void 0,{timeout:Math.min(t,3e4)}));let u=await e.evaluate(()=>{let l=globalThis;return {panelVisible:l.__threeBlocksSmoke?.stats?.panelVisible,textures:Number(l.__threeBlocksSmoke?.stats?.textures)||0,panelAttached:l.document.querySelector("[data-three-blocks-stats-mode]")!==null}});if(!a&&(u.panelVisible!==!1||u.textures!==0||u.panelAttached))throw new Error("Generated stats panel is not default-off before browser-smoke activation.");s="stats-enable",await e.evaluate(async()=>{let n=globalThis.__threeBlocksSmoke?.stats;if(!n||typeof n.setPanelVisible!="function"||typeof n.setPanelMode!="function")throw new Error("Generated stats panel controls are unavailable.");if(await Reflect.apply(n.setPanelVisible,n,[!0])!==!0)throw new Error("Generated stats panel could not be enabled.");if(await Reflect.apply(n.setPanelMode,n,["expanded"])!==!0)throw new Error("Generated stats panel could not be expanded.")}),s="stats-expanded",await e.waitForFunction(()=>{let l=globalThis;return l.__threeBlocksSmoke?.stats?.panelVisible===!0&&l.document.querySelector('[data-three-blocks-stats-mode="expanded"]')!==null},void 0,{timeout:Math.min(t,3e4)}),s="stats-initial-texture",await e.waitForFunction(l=>Number(globalThis.__threeBlocksSmoke?.stats?.textures)>l,u.textures,{timeout:Math.min(t,3e4)}),s="snapshot";let i=await e.evaluate(()=>{let l=globalThis,n=l.__threeBlocksSmoke,m=l.document.querySelector("#app"),c=l.document.querySelector("#scene"),p=l.document.querySelector("main")??m;if(!n||typeof n.restartWorker!="function"||!m||!c||!p||typeof n.diagnostics?.workerId!="string")throw new Error("Generated worker restart diagnostics are unavailable.");return l.__threeBlocksWorkerRestartProbe={app:m,content:p,canvas:c},{workerId:n.diagnostics.workerId,generation:n.worker.generation,restartCount:n.restart.count,snapshots:n.stats.snapshots,textures:n.stats.textures}});s="restart-call",await e.evaluate(async()=>{let l=globalThis,n=l.__threeBlocksSmoke?.restartWorker;if(typeof n!="function")throw new Error("Generated restartWorker() is unavailable.");await Reflect.apply(n,l.__threeBlocksSmoke,["browser smoke worker restart"]);}),s="restart-readiness",await e.waitForFunction(l=>{let m=globalThis.__threeBlocksSmoke,c=m?.readiness;return typeof m?.diagnostics?.workerId=="string"&&m.diagnostics.workerId!==l.workerId&&Number(m.worker?.generation)>l.generation&&m.restart?.stateReplayed===!0&&c?.workerReady===!0&&c.assetsReady===!0&&c.compileEnd===!0&&c.firstFrame===!0&&(!l.textEnabled||c.textReady===!0)},{workerId:i.workerId,generation:i.generation,textEnabled:o},{timeout:Math.min(t,45e3)}),s="stats-snapshot",await e.waitForFunction(l=>Number(globalThis.__threeBlocksSmoke?.stats?.snapshots)>l,i.snapshots,{timeout:Math.min(t,3e4)}),s="stats-texture",await e.waitForFunction(l=>Number(globalThis.__threeBlocksSmoke?.stats?.textures)>l,i.textures,{timeout:Math.min(t,3e4)});let y=await e.evaluate(l=>{let n=globalThis,m=n.__threeBlocksSmoke,c=n.__threeBlocksWorkerRestartProbe,p=m?.readiness;if(!m||!c||!p)throw new Error("Generated restart evidence disappeared.");return {requested:!0,appIdentityStable:c.app===n.document.querySelector("#app"),contentIdentityStable:c.content===(n.document.querySelector("main")??n.document.querySelector("#app")),canvasReplaced:m.restart.canvasReplaced&&c.canvas!==n.document.querySelector("#scene"),workerIdentityChanged:typeof m.diagnostics?.workerId=="string"&&m.diagnostics.workerId!==l.workerId,generationAdvanced:m.worker.generation===l.generation+1,restartCountAdvanced:m.restart.count===l.restartCount+1,stateReplayed:m.restart.stateReplayed&&m.restart.lastReason==="browser smoke worker restart",readinessRestored:p.workerReady===!0&&p.assetsReady===!0&&p.compileEnd===!0&&p.firstFrame===!0&&(!l.textEnabled||p.textReady===!0),shaderModeStable:m.diagnostics?.shaderMode===l.expectedShaderMode,statsSnapshotsAdvanced:m.stats.snapshots>l.snapshots,statsTextureTransferred:m.stats.textures>l.textures,statsTextureStopped:!1,error:null}},{...i,textEnabled:o,expectedShaderMode:r});s="stats-disable",await e.evaluate(async()=>{let n=globalThis.__threeBlocksSmoke?.stats;if(!n||typeof n.setPanelVisible!="function")throw new Error("Generated stats visibility control disappeared before disable.");if(await Reflect.apply(n.setPanelVisible,n,[!1])!==!0)throw new Error("Generated stats panel could not be disabled.")}),await e.waitForFunction(()=>globalThis.__threeBlocksSmoke?.stats?.panelVisible===!1,void 0,{timeout:Math.min(t,3e4)}),await e.waitForTimeout(750);let f=await e.evaluate(()=>Number(globalThis.__threeBlocksSmoke?.stats?.textures)||0);await e.waitForTimeout(1100);let b=await e.evaluate(()=>Number(globalThis.__threeBlocksSmoke?.stats?.textures)||0);if(b!==f)throw new Error(`Stats textures advanced after disable (${f} -> ${b}).`);return {...y,statsTextureStopped:!0}}catch(a){return {...K,requested:true,error:`${s}: ${a instanceof Error?a.message:String(a)}`}}}a(ir,"exerciseWorkerRestart");function D(e){return [...new Set(e)].sort((t,o)=>t.localeCompare(o))}a(D,"sortedUnique");function dr(e,t,o){let r=D(e),s=D(t),a=o?D([...r,...s].filter(i=>/MSDF atlases are missing code points:/iu.test(i))):[],u=new Set(a);return {console:r.filter(i=>!u.has(i)),page:s.filter(i=>!u.has(i)),resolved:a}}a(dr,"classifyRecoveredTextErrors");function cr(e){return e.replace(/\u001b\[[0-?]*[ -/]*[@-~]/gu,"")}a(cr,"stripTerminalControl");function ur(e,t,o){let r=e.config.base.startsWith("/")?e.config.base:"/";return new URL(o.replace(/^\/+/,""),`${t}${r.endsWith("/")?r:`${r}/`}`).href}a(ur,"projectUrl");async function vr(e){let{vite:{createLogger:t,createServer:o}}=await Re();if(e.forceWebgl===true&&e.unsupportedWorker===true)throw new Error("Browser smoke forceWebgl and unsupportedWorker modes are mutually exclusive.");if(e.unsupportedWorker===true&&e.expectTextGenerationFailure===true)throw new Error("Browser smoke unsupportedWorker and expectTextGenerationFailure modes are mutually exclusive.");let r=await realpath(e.root),s=Ee(e.route),a$1=V(e.timeoutMs,"Browser smoke timeoutMs",1e3,15*6e4,Se),u=V(e.settleMs,"Browser smoke settleMs",0,1e4,1e3),i={width:V(e.viewport?.width,"Browser smoke viewport width",64,8192,1024),height:V(e.viewport?.height,"Browser smoke viewport height",64,8192,640)},y=Be(e.minimumLuminance,"Browser smoke minimumLuminance",0,255,2),f,b,l,n,m=false,c=$(void 0,false),p=[],P=null,U=le,w={requested:e.hmrModule!==void 0,module:e.hmrModule??null,dispatched:false,acknowledged:false,lifecycleStable:e.hmrModule===void 0,sourceUnchanged:e.hmrModule===void 0,evidenceSource:"public-runtime-node-probe",evidence:le,restart:K,error:e.hmrModule===void 0?null:"HMR was not reached."},T=false,R=false,q={fatalVisible:false,code:null,detail:null},B={states:[],fallbackObserved:false,recovered:false,visibleElements:0,totalElements:0},g={snapshots:0,textures:0,shaderMode:null,mainPanels:false},A=[],I=0,L=0,_={console:[],page:[]},O,z=process.env.PATH;process.env.PATH=[F.join(r,"node_modules",".bin"),z].filter(Boolean).join(F.delimiter);try{let k=t("silent");k.warn=j=>{A.push(cr(j));},f=await o({root:r,logLevel:"silent",customLogger:k,plugins:[Ke()],optimizeDeps:{force:!0,include:[...Qe]},server:{host:"127.0.0.1",port:0,strictPort:!1}}),await f.listen();let v=f.httpServer?.address();if(!v||typeof v=="string")throw new Error("Vite did not expose an ephemeral TCP address.");let S=`http://127.0.0.1:${v.port}`;b=await launchNodeRenderer(),l=await b.newContext({viewport:i}),await l.addInitScript({content:`
228
+ (() => {
229
+ const key = '__three-blocks-text-fallback-states-v1';
230
+ let states = [];
231
+ try { states = JSON.parse( sessionStorage.getItem( key ) || '[]' ); } catch {}
232
+ const probe = globalThis.__threeBlocksTextFallbackProbe = { states };
233
+ const record = value => {
234
+ if ( typeof value !== 'string' || value.length === 0 || probe.states.at( -1 ) === value || probe.states.length >= 32 ) return;
235
+ probe.states.push( value );
236
+ try { sessionStorage.setItem( key, JSON.stringify( probe.states ) ); } catch {}
237
+ };
238
+ const inspect = node => {
239
+ if ( node && node.nodeType === 1 ) record( node.getAttribute( 'data-three-blocks-text-state' ) );
240
+ };
241
+ new MutationObserver( records => {
242
+ for ( const mutation of records ) {
243
+ inspect( mutation.target );
244
+ for ( const node of mutation.addedNodes || [] ) {
245
+ inspect( node );
246
+ if ( node.querySelectorAll ) for ( const child of node.querySelectorAll( '[data-three-blocks-text-state]' ) ) inspect( child );
247
+ }
248
+ }
249
+ } ).observe( document, { subtree: true, childList: true, attributes: true, attributeFilter: [ 'data-three-blocks-text-state' ] } );
250
+ })();
251
+ `}),e.forceWebgl===!0&&await l.addInitScript(()=>{Object.defineProperty(navigator,"gpu",{configurable:!0,value:void 0});}),e.unsupportedWorker===!0&&await l.addInitScript(()=>{Object.defineProperty(globalThis,"Worker",{configurable:!0,value:void 0});}),n=await l.newPage();let C=n;if(O=_e(n),n.on("console",j=>{/WebGPU is not available, running under WebGL2 backend/iu.test(j.text())&&(R=!0);}),await n.goto(ur(f,S,s),{waitUntil:"domcontentloaded",timeout:a$1}),e.unsupportedWorker===!0)T=await ve(async()=>{await se(C,a(async()=>{await C.waitForFunction(()=>globalThis.document.querySelector("#three-blocks-dev-overlay")?.shadowRoot?.querySelector(".dot")?.dataset.tone==="error",void 0,{timeout:Math.min(a$1,15e3)});},"waitForFailure"),a$1);},()=>C.evaluate(()=>"gpu"in navigator&&navigator.gpu!==void 0)),q=await Je(n),c=$(await H(n),!1);else {let j=a(()=>e.expectTextGenerationFailure===!0?ge(C,a$1):Y(C,!1,a$1),"initialReadiness");T=await ve(()=>se(C,j,a$1),()=>C.evaluate(()=>"gpu"in navigator&&navigator.gpu!==void 0));let E=await nr(n,j,a$1);if(m=E.textEnabled,p=E.codecs,P=E.receipt,U=E.hmrEvidence,e.expectTextGenerationFailure===!0){if(!E.textEnabled)throw new Error("Expected text-generation failure mode requires a text-enabled project.");await ge(n,a$1);let W=performance.now()+Math.min(a$1,3e4);for(;!A.some(qe=>/automatic atlas generation failed/iu.test(qe));){if(performance.now()>=W)throw new Error("Timed out waiting for the automatic text-generation failure warning.");await n.waitForTimeout(50);}c=$(await H(n),!0);}else if(await Y(n,E.textEnabled,a$1),c=$(await H(n),E.textEnabled),E.textEnabled&&c.textReady&&(p=p.map(W=>W.name==="ktx2"?{...W,decoded:!0,evidence:"text-atlas-decoded",blocker:null}:W)),w=await lr(f,n,r,e.hmrModule,a$1,E.textEnabled,U),e.hmrModule!==void 0){let W=await ir(n,a$1,E.textEnabled,E.receipt.shaders.mode);w={...w,restart:W},c=$(await H(n),E.textEnabled);}}u>0&&await n.waitForTimeout(u),B=await ke(n),g=await X(n);let Ve=await n.screenshot({type:"png"});I=ae(Ve),L=await ie(n);}catch(k){if(n!==void 0)try{c=$(await H(n),m),B=await ke(n),g=await X(n);let v=await n.screenshot({type:"png"});I=ae(v),L=await ie(n);}catch(v){_.page.push(`Failure diagnostics could not be captured: ${v instanceof Error?v.message:String(v)}`);}_.page.push(k instanceof Error?k.message:String(k));}finally{O!==void 0&&(_.console.push(...O.console),_.page.push(...O.page)),await l?.close().catch(S=>{_.page.push(`Browser context cleanup failed: ${S instanceof Error?S.message:String(S)}`);}),await b?.close().catch(S=>{_.page.push(`Browser cleanup failed: ${S instanceof Error?S.message:String(S)}`);});let k=f?.httpServer,v=k?Reflect.get(k,"closeAllConnections"):void 0;k&&typeof v=="function"&&Reflect.apply(v,k,[]),await f?.close().catch(S=>{_.page.push(`Vite cleanup failed: ${S instanceof Error?S.message:String(S)}`);}),z===void 0?delete process.env.PATH:process.env.PATH=z;}let J=Number(I.toFixed(2)),M=Number(L.toFixed(2)),ue=I<=y&&L<=y,Z=dr(_.console,_.page,B.recovered),me=Z.console,ye=Z.page,Pe=Z.resolved,fe=c.worker&&c.workerReady&&c.assetsReady&&c.compileEnd&&c.textReady&&c.firstFrame,Te=p.length===3&&p.every(k=>k.state!=="error"),Me=Object.values(w.evidence).every(Boolean),Ce=!w.restart.requested||w.restart.error===null&&[w.restart.appIdentityStable,w.restart.contentIdentityStable,w.restart.canvasReplaced,w.restart.workerIdentityChanged,w.restart.generationAdvanced,w.restart.restartCountAdvanced,w.restart.stateReplayed,w.restart.readinessRestored,w.restart.shaderModeStable,w.restart.statsSnapshotsAdvanced,w.restart.statsTextureTransferred,w.restart.statsTextureStopped].every(Boolean),pe=!w.requested||w.dispatched&&w.acknowledged&&w.lifecycleStable&&w.sourceUnchanged&&Me&&Ce&&w.error===null,we=A.filter(k=>/automatic atlas generation failed/iu.test(k)),Fe=we.reduce((k,v)=>k+(v.match(/three-blocks text generate/gu)?.length??0),0),Ae=e.expectTextGenerationFailure===true&&m&&B.fallbackObserved&&!B.recovered&&B.totalElements>0&&B.visibleElements===B.totalElements&&we.length===1&&Fe===1,$e=e.unsupportedWorker===true&&q.fatalVisible&&q.code==="render-worker-unavailable"&&!c.workerReady&&!c.compileEnd&&!c.firstFrame,Ie=e.unsupportedWorker===true?"unsupported-worker":e.forceWebgl===true?"WebGL-fallback":"WebGPU-first",Le=e.unsupportedWorker===true?"none":fe?e.forceWebgl===true||!T?"WebGL":"WebGPU":"unknown",We=c.workerReady&&c.compileEnd&&c.firstFrame,h={schemaVersion:1,command:"browser smoke",execution:"node",passed:e.unsupportedWorker===true?$e:e.expectTextGenerationFailure===true?Ae:fe&&Te&&pe&&!ue&&me.length===0&&ye.length===0,scene:s,lifecycle:c,renderer:{requested:Ie,active:Le,navigatorGpu:T,workerOwned:We,fallbackDiagnostic:R},compatibility:{...q,silentMainThreadRenderer:e.unsupportedWorker===true&&(c.compileEnd||c.firstFrame)},receipt:P,textFallback:B,warnings:D(A),rendering:{luminance:J,panelLuminance:M,threshold:y,blackFrame:ue},codecs:p,hmr:w,errors:{console:me,page:ye,resolved:Pe}};if(h.passed&&e.unsupportedWorker!==true&&e.expectTextGenerationFailure!==true){if(h.receipt===null||h.lifecycle.backend==="unknown"||h.renderer.active!=="WebGPU"&&h.renderer.active!=="WebGL")throw new Error("A successful browser smoke cannot write runtime status without an observed backend and renderer/build receipt.");let k=h.hmr.requested,v=k?pe:null,S={schemaVersion:1,observedAt:new Date().toISOString(),worker:{backend:h.lifecycle.backend,renderer:h.renderer.active,protocolVersion:1},assets:{codecs:h.codecs.map(C=>({name:C.name,available:C.state==="ready",decoded:C.decoded})),resources:0},hmr:{capabilities:{scene:true,component:true,assetManifest:true,workerRestart:true},outcome:{attempted:k,succeeded:v,rollbackPreserved:k?h.hmr.evidence.rollbackPreserved:null,workerRestarted:h.hmr.restart.requested&&h.hmr.restart.workerIdentityChanged}},stats:{snapshots:g.snapshots,textures:g.textures,workerProfiler:g.snapshots>0,mainPanels:g.mainPanels},lifecycle:{state:"first frame",workerReady:h.lifecycle.workerReady,assetsReady:h.lifecycle.assetsReady,compiled:h.lifecycle.compileEnd,firstFrame:h.lifecycle.firstFrame},shaders:{mode:g.shaderMode??h.receipt.shaders.mode,pipelines:h.receipt.shaders.pipelines},...h.receipt.text===void 0?{}:{text:{state:h.receipt.text.state,atlases:h.receipt.text.atlases,glyphs:h.receipt.text.glyphs,requiredGlyphs:h.receipt.text.glyphs}},error:null};await Xe(r,S);}return h}a(vr,"runBrowserSmoke");function xr(e){let t=e.lifecycle,o=[`${e.passed?"\u2713":"\u2717"} Browser ${e.scene} \xB7 worker ${t.worker&&t.workerReady?"ready":"failed"} \xB7 assets ${t.assetsReady?"ready":"failed"} \xB7 compile ${t.compileEnd?"ready":"failed"}`,` Renderer ${e.renderer.active} \xB7 ${e.renderer.workerOwned?"worker-owned":e.renderer.requested}`,` Frame ${e.rendering.luminance.toFixed(2)} \xB7 panel ${e.rendering.panelLuminance.toFixed(2)}${e.rendering.blackFrame?" \xB7 black":""}`,` Codecs ${e.codecs.map(r=>`${r.name} ${r.state}${r.decoded?" decoded":""}`).join(" \xB7 ")||"not observed"}`];e.compatibility.fatalVisible&&o.push(` Compatibility ${e.compatibility.detail??"fatal compatibility screen visible"}`),e.textFallback.states.length>0&&o.push(` Text ${e.textFallback.states.join(" \u2192 ")}`),e.hmr.requested&&o.push(` HMR ${e.hmr.acknowledged&&e.hmr.sourceUnchanged&&Object.values(e.hmr.evidence).every(Boolean)?"ready":"failed"} \xB7 ${e.hmr.module??"unknown module"}`),e.hmr.restart.requested&&o.push(` Restart ${e.hmr.restart.error===null&&e.hmr.restart.workerIdentityChanged&&e.hmr.restart.stateReplayed?"ready":"failed"} \xB7 worker/state/stats`);for(let r of e.warnings)o.push(` Warning ${r}`);for(let r of e.errors.console)o.push(` Console ${r}`);for(let r of e.errors.page)o.push(` Page ${r}`);for(let r of e.errors.resolved)o.push(` Recovered ${r}`);e.hmr.error&&o.push(` HMR error ${e.hmr.error}`),e.hmr.restart.error&&o.push(` Restart error ${e.hmr.restart.error}`);for(let r of e.codecs)r.error&&o.push(` ${r.name} error ${r.error}`);return o.join(`
252
+ `)}a(xr,"formatBrowserSmokeReport");async function Sr(e){let{vite:{build:t,preview:o}}=await Re(),r=await realpath(e.root),s=(e.routes===void 0||e.routes.length===0?["/"]:e.routes).map(Ee),a=V(e.timeoutMs,"Browser preview timeoutMs",1e3,15*6e4,Se),u=V(e.settleMs,"Browser preview settleMs",0,1e4,500),i={width:V(e.viewport?.width,"Browser preview viewport width",64,8192,1024),height:V(e.viewport?.height,"Browser preview viewport height",64,8192,640)},y=Be(e.minimumLuminance,"Browser preview minimumLuminance",0,255,2),f=e.expectShaders??"precompiled",b=e.text===true,l=[],n,m,c=process.env.PATH;process.env.PATH=[F.join(r,"node_modules",".bin"),c].filter(Boolean).join(F.delimiter);try{await t({root:r,logLevel:"warn",...e.buildMode===void 0?{}:{mode:e.buildMode}}),n=await o({root:r,logLevel:"warn",preview:{host:"127.0.0.1",port:0,strictPort:!1,open:!1}});let p=n.httpServer?.address();if(!p||typeof p=="string")throw new Error("Vite preview did not expose an ephemeral TCP address.");let P=n.config.base.startsWith("/")?n.config.base:"/",U=`http://127.0.0.1:${p.port}${P.endsWith("/")?P:`${P}/`}`;m=await launchNodeRenderer();for(let w of s){let T=await m.newContext({viewport:i}),R=await T.newPage(),q=_e(R),B=[],g=$(void 0,b),A=null,I=0,L=0;try{await R.goto(new URL(w.replace(/^\/+/,""),U).href,{waitUntil:"domcontentloaded",timeout:a}),await Y(R,b,a),u>0&&await R.waitForTimeout(u),g=$(await H(R),b),A=(await X(R)).shaderMode;let M=await R.screenshot({type:"png"});I=ae(M),L=await ie(R);}catch(M){try{g=$(await H(R),b),A=(await X(R)).shaderMode;}catch{}B.push(M instanceof Error?M.message:String(M));}finally{await T.close().catch(M=>{B.push(`Browser context cleanup failed: ${M instanceof Error?M.message:String(M)}`);});}let _=D(q.console),O=D([...q.page,...B]),z=g.worker&&g.workerReady&&g.assetsReady&&g.compileEnd&&g.textReady&&g.firstFrame,J=I<=y&&L<=y;l.push({route:w,passed:z&&!J&&A===f&&_.length===0&&O.length===0,lifecycle:g,shaderMode:A,rendering:{luminance:Number(I.toFixed(2)),panelLuminance:Number(L.toFixed(2)),threshold:y,blackFrame:J},errors:{console:_,page:O}});}}finally{await m?.close().catch(()=>{});let p=n?.httpServer,P=p?Reflect.get(p,"closeAllConnections"):void 0;p&&typeof P=="function"&&Reflect.apply(P,p,[]),await n?.close().catch(()=>{}),c===void 0?delete process.env.PATH:process.env.PATH=c;}return {schemaVersion:1,command:"browser preview",execution:"node",passed:l.length>0&&l.every(p=>p.passed),buildMode:e.buildMode??null,expectShaders:f,routes:l}}a(Sr,"runBrowserPreview");function Rr(e){let t=[`${e.passed?"\u2713":"\u2717"} Preview production build${e.buildMode===null?"":` \xB7 --mode ${e.buildMode}`} \xB7 expects shaders ${e.expectShaders}`];for(let o of e.routes){let r=o.lifecycle;t.push(` ${o.passed?"\u2713":"\u2717"} ${o.route} \xB7 worker ${r.worker&&r.workerReady?"ready":"failed"} \xB7 compile ${r.compileEnd?"ready":"failed"} \xB7 shaders ${o.shaderMode??"unobserved"} \xB7 frame ${o.rendering.luminance.toFixed(2)}${o.rendering.blackFrame?" \xB7 black":""}`);for(let s of o.errors.console)t.push(` Console ${s}`);for(let s of o.errors.page)t.push(` Page ${s}`);}return t.join(`
253
+ `)}a(Rr,"formatBrowserPreviewReport");export{$ as a,ae as b,ve as c,Qe as d,dr as e,vr as f,xr as g,Sr as h,Rr as i};
@@ -1,2 +1 @@
1
- #!/usr/bin/env node
2
- import {a}from'./chunk-HOZDD6PW.js';import {createHash,randomUUID}from'crypto';import {lstat,open,realpath,mkdir,rename,rm,link,readdir}from'fs/promises';import a$1 from'path';var L=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 h(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"?e.code:void 0}a(h,"errorCode");function R(e){return createHash("sha256").update(e).digest("hex")}a(R,"sha256");async function D(e){try{return await lstat(e),!0}catch(i){if(h(i)==="ENOENT")return false;throw i}}a(D,"pathExists");function m(e,i){let t=a$1.relative(e,i);return t===""||!a$1.isAbsolute(t)&&t!==".."&&!t.startsWith(`..${a$1.sep}`)}a(m,"isWithin");function w(e){return JSON.stringify(e)}a(w,"displayPath");async function F(e,i,t){let n=await open(e,"r");try{let[r,o,l]=await Promise.all([lstat(e),n.stat(),realpath(e)]);if(r.isSymbolicLink())throw new Error(`${t} must not be a symbolic link: ${w(e)}.`);if(!o.isFile())throw new Error(`${t} must be a regular file: ${w(e)}.`);if(o.size>i)throw new Error(`${t} exceeds the ${i}-byte inspection limit: ${w(e)}.`);let c=await n.readFile();if(c.byteLength>i)throw new Error(`${t} grew beyond the ${i}-byte inspection limit while being read.`);return {path:l,data:c}}finally{await n.close();}}a(F,"readBoundedRegularFile");async function U(e,i){let t=a$1.dirname(e);await mkdir(t,{recursive:true});try{if((await lstat(e)).isSymbolicLink())throw new Error(`Atomic write target must not be a symbolic link: ${w(e)}.`)}catch(o){if(h(o)!=="ENOENT")throw o}let n=a$1.join(t,`.${a$1.basename(e)}.${process.pid}.${randomUUID()}.tmp`),r;try{r=await open(n,"wx",384),await r.writeFile(i),await r.sync(),await r.close(),r=void 0,await rename(n,e);}finally{await r?.close().catch(()=>{}),await rm(n,{force:true});}}a(U,"writeAtomicRegularFile");async function O(e,i){let t=a$1.dirname(e);await mkdir(t,{recursive:true});let n=a$1.join(t,`.${a$1.basename(e)}.${process.pid}.${randomUUID()}.tmp`),r;try{r=await open(n,"wx",384),await r.writeFile(i),await r.sync(),await r.close(),r=void 0;try{return await link(n,e),!0}catch(o){if(h(o)==="EEXIST")return !1;throw o}}finally{await r?.close().catch(()=>{}),await rm(n,{force:true});}}a(O,"writeNewRegularFile");async function W(e,i,t){return F(e,i,t)}a(W,"readExternalRegularFile");async function $(e,i,t){let n=a$1.resolve(e),r=a$1.resolve(i);if(!m(n,r))throw new Error(`${t} escapes its allowed directory.`);let o=await lstat(r);if(o.isSymbolicLink())throw new Error(`${t} must not be a symbolic link.`);if(!o.isDirectory())throw new Error(`${t} must be a directory.`);let[l,c]=await Promise.all([realpath(n),realpath(r)]);if(!m(l,c))throw new Error(`${t} resolves outside its allowed directory.`);return c}a($,"canonicalDirectoryWithin");async function j(e,i,t,n){let r=a$1.resolve(e),o=a$1.resolve(i);if(!m(r,o)||r===o)throw new Error(`${n} escapes its allowed directory.`);let l=await F(o,t,n),c=await realpath(r);if(!m(c,l.path)||c===l.path)throw new Error(`${n} resolves outside its allowed directory.`);return l}a(j,"readRegularFileWithin");async function z(e,i,t,n=8192){let o=[await $(e,i,"Inspected directory")],l=[],c=0;for(;o.length>0;){let p=o.shift();if(p===void 0)break;let v=(await readdir(p,{withFileTypes:true})).sort((d,u)=>d.name.localeCompare(u.name));for(let d of v){if(c+=1,c>n)throw new Error(`Inspected directory exceeds the ${n}-entry limit.`);let u=a$1.join(p,d.name);if(d.isSymbolicLink())throw new Error(`Inspected directory contains a symbolic link: ${w(a$1.relative(e,u))}.`);if(d.isDirectory()){o.push(await $(e,u,"Nested inspected directory"));continue}if(d.isFile()&&t(d.name))l.push(u);else if(t(d.name))throw new Error(`Semantic input is not a regular file: ${w(u)}.`)}}return l.sort()}a(z,"listRegularFilesRecursively");export{L as a,h as b,R as c,D as d,m as e,U as f,O as g,W as h,$ as i,j,z as k};
1
+ import {a}from'./chunk-7X4DHW36.js';import {createHash,randomUUID}from'crypto';import {lstat,open,realpath,mkdir,rename,rm,link,readdir}from'fs/promises';import a$1 from'path';var L=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 h(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"?e.code:void 0}a(h,"errorCode");function R(e){return createHash("sha256").update(e).digest("hex")}a(R,"sha256");async function D(e){try{return await lstat(e),!0}catch(i){if(h(i)==="ENOENT")return false;throw i}}a(D,"pathExists");function m(e,i){let t=a$1.relative(e,i);return t===""||!a$1.isAbsolute(t)&&t!==".."&&!t.startsWith(`..${a$1.sep}`)}a(m,"isWithin");function w(e){return JSON.stringify(e)}a(w,"displayPath");async function F(e,i,t){let n=await open(e,"r");try{let[r,o,l]=await Promise.all([lstat(e),n.stat(),realpath(e)]);if(r.isSymbolicLink())throw new Error(`${t} must not be a symbolic link: ${w(e)}.`);if(!o.isFile())throw new Error(`${t} must be a regular file: ${w(e)}.`);if(o.size>i)throw new Error(`${t} exceeds the ${i}-byte inspection limit: ${w(e)}.`);let c=await n.readFile();if(c.byteLength>i)throw new Error(`${t} grew beyond the ${i}-byte inspection limit while being read.`);return {path:l,data:c}}finally{await n.close();}}a(F,"readBoundedRegularFile");async function U(e,i){let t=a$1.dirname(e);await mkdir(t,{recursive:true});try{if((await lstat(e)).isSymbolicLink())throw new Error(`Atomic write target must not be a symbolic link: ${w(e)}.`)}catch(o){if(h(o)!=="ENOENT")throw o}let n=a$1.join(t,`.${a$1.basename(e)}.${process.pid}.${randomUUID()}.tmp`),r;try{r=await open(n,"wx",384),await r.writeFile(i),await r.sync(),await r.close(),r=void 0,await rename(n,e);}finally{await r?.close().catch(()=>{}),await rm(n,{force:true});}}a(U,"writeAtomicRegularFile");async function O(e,i){let t=a$1.dirname(e);await mkdir(t,{recursive:true});let n=a$1.join(t,`.${a$1.basename(e)}.${process.pid}.${randomUUID()}.tmp`),r;try{r=await open(n,"wx",384),await r.writeFile(i),await r.sync(),await r.close(),r=void 0;try{return await link(n,e),!0}catch(o){if(h(o)==="EEXIST")return !1;throw o}}finally{await r?.close().catch(()=>{}),await rm(n,{force:true});}}a(O,"writeNewRegularFile");async function W(e,i,t){return F(e,i,t)}a(W,"readExternalRegularFile");async function $(e,i,t){let n=a$1.resolve(e),r=a$1.resolve(i);if(!m(n,r))throw new Error(`${t} escapes its allowed directory.`);let o=await lstat(r);if(o.isSymbolicLink())throw new Error(`${t} must not be a symbolic link.`);if(!o.isDirectory())throw new Error(`${t} must be a directory.`);let[l,c]=await Promise.all([realpath(n),realpath(r)]);if(!m(l,c))throw new Error(`${t} resolves outside its allowed directory.`);return c}a($,"canonicalDirectoryWithin");async function j(e,i,t,n){let r=a$1.resolve(e),o=a$1.resolve(i);if(!m(r,o)||r===o)throw new Error(`${n} escapes its allowed directory.`);let l=await F(o,t,n),c=await realpath(r);if(!m(c,l.path)||c===l.path)throw new Error(`${n} resolves outside its allowed directory.`);return l}a(j,"readRegularFileWithin");async function z(e,i,t,n=8192){let o=[await $(e,i,"Inspected directory")],l=[],c=0;for(;o.length>0;){let p=o.shift();if(p===void 0)break;let v=(await readdir(p,{withFileTypes:true})).sort((d,u)=>d.name.localeCompare(u.name));for(let d of v){if(c+=1,c>n)throw new Error(`Inspected directory exceeds the ${n}-entry limit.`);let u=a$1.join(p,d.name);if(d.isSymbolicLink())throw new Error(`Inspected directory contains a symbolic link: ${w(a$1.relative(e,u))}.`);if(d.isDirectory()){o.push(await $(e,u,"Nested inspected directory"));continue}if(d.isFile()&&t(d.name))l.push(u);else if(t(d.name))throw new Error(`Semantic input is not a regular file: ${w(u)}.`)}}return l.sort()}a(z,"listRegularFilesRecursively");export{L as a,h as b,R as c,D as d,m as e,U as f,O as g,W as h,$ as i,j,z as k};
@@ -0,0 +1,3 @@
1
+ import {b}from'./chunk-ZG3LO3VB.js';import {a as a$1,c,d,h,e}from'./chunk-ECQE4D2U.js';import {a}from'./chunk-7X4DHW36.js';import {randomUUID}from'crypto';import {mkdir,lstat,realpath,writeFile,rename,rm,readFile}from'fs/promises';import p from'path';import {fileURLToPath}from'url';import K from'zlib';import {VK_FORMAT_R16G16B16A16_SFLOAT,KHR_SUPERCOMPRESSION_NONE,read,KHR_SUPERCOMPRESSION_ZSTD,write}from'ktx-parse';import {launchNodeRenderer}from'@three-blocks/devtools/node';var D="/__three-blocks/devtools/environment-bake",J="/__three-blocks/devtools/environment-bake/upload",T="virtual:three-blocks-devtools/environment-bake.ts",C=`\0${T}`,Y=`/@id/__x00__${T}`,Q="src/assets/environment/room-environment.pmrem.ktx2",_=128*1024*1024,q=1;function N(e,n,t,r,o){let m=e??o;if(!Number.isSafeInteger(m)||m<t||m>r)throw new Error(`${n} must be an integer in ${t}...${r}.`);return m}a(N,"boundedInteger");function P(e){let n=N(e,"Environment cube size",16,1024,256);if((n&n-1)!==0)throw new Error("Environment cube size must be a power of two.");return n}a(P,"validateEnvironmentCubeSize");function ee(){return K}a(ee,"zstdFunctions");function te(e){if(!/^[0-9A-Za-z][0-9A-Za-z.+_-]{0,63}$/u.test(e))throw new Error("Browser reported an invalid Three.js revision.");return e}a(te,"boundedThreeRevision");function ne(e){if(e.vkFormat!==VK_FORMAT_R16G16B16A16_SFLOAT)throw new Error("RoomEnvironment bake must be RGBA16F KTX2.");if(e.typeSize!==2)throw new Error("RoomEnvironment RGBA16F KTX2 must use a two-byte component type.");if(e.supercompressionScheme!==KHR_SUPERCOMPRESSION_NONE)throw new Error("Browser RoomEnvironment KTX2 must be uncompressed before deterministic encoding.");if(!Number.isSafeInteger(e.pixelWidth)||e.pixelWidth<=0||e.pixelWidth>8192||!Number.isSafeInteger(e.pixelHeight)||e.pixelHeight<=0||e.pixelHeight>8192||e.pixelDepth!==0||e.layerCount!==0||e.faceCount!==1||e.levels.length!==1||e.levels[0]===void 0)throw new Error("RoomEnvironment KTX2 has invalid CubeUV dimensions or topology.");let n=e.pixelWidth*e.pixelHeight*8;if(!Number.isSafeInteger(n)||n>_)throw new Error("RoomEnvironment KTX2 decoded payload exceeds the safety limit.");let t=e.levels[0],r=n+e.pixelHeight*256;if(t.levelData.byteLength<n||t.levelData.byteLength>r||t.levelData.byteLength%8!==0||t.uncompressedByteLength!==t.levelData.byteLength)throw new Error(`RoomEnvironment KTX2 level byte count ${t.levelData.byteLength} is outside the bounded RGBA16F CubeUV layout.`);return e.levels.map(o=>new Uint8Array(o.levelData))}a(ne,"validateRawContainer");function re(e,n){return e.byteLength===n.byteLength&&Buffer.from(e).equals(Buffer.from(n))}a(re,"sameBytes");function oe(e,n){let t=P(n.cubeSize),r=te(n.threeRevision);if(e.byteLength===0||e.byteLength>a$1.texture)throw new Error("RoomEnvironment KTX2 input exceeds the bounded texture size.");let o=read(e),m=ne(o),d=n.compression??"zstd",c$1=ee(),u=K.constants.ZSTD_c_compressionLevel;if(d==="zstd"&&(c$1.zstdCompressSync===void 0||c$1.zstdDecompressSync===void 0||u===void 0))throw new Error("This Node.js runtime does not provide deterministic Zstandard support; use --no-zstd explicitly to opt out.");if(o.supercompressionScheme=d==="zstd"?KHR_SUPERCOMPRESSION_ZSTD:KHR_SUPERCOMPRESSION_NONE,o.levelCount=m.length,o.levels=m.map(a=>{let f=d==="zstd"?c$1.zstdCompressSync?.(a,{params:{[u]:19}}):void 0;return {levelData:f===void 0?a:new Uint8Array(f.buffer,f.byteOffset,f.byteLength),uncompressedByteLength:a.byteLength}}),d==="zstd")for(let a of o.dataFormatDescriptor)a.bytesPlane=[0,0,0,0,0,0,0,0];o.keyValue={KTXorientation:"rd",KTXwriter:`three-blocks RoomEnvironment \xB7 three r${r}`};let i=write(o,{keepWriter:true});if(i.byteLength===0||i.byteLength>a$1.texture)throw new Error("Encoded RoomEnvironment KTX2 exceeds the bounded texture size.");let l=read(i);if(l.vkFormat!==VK_FORMAT_R16G16B16A16_SFLOAT||l.pixelWidth!==o.pixelWidth||l.pixelHeight!==o.pixelHeight||l.supercompressionScheme!==o.supercompressionScheme||l.keyValue.KTXorientation!=="rd"||l.levels.length!==m.length)throw new Error("RoomEnvironment KTX2 header failed round-trip validation.");for(let a=0;a<l.levels.length;a+=1){let f=l.levels[a],g=m[a];if(f===void 0||g===void 0)throw new Error(`RoomEnvironment KTX2 level ${a} is missing after round-trip.`);let E=d==="zstd"?c$1.zstdDecompressSync?.(f.levelData):f.levelData;if(E===void 0||f.uncompressedByteLength!==g.byteLength||!re(E,g))throw new Error(`RoomEnvironment KTX2 level ${a} failed byte-for-byte round-trip validation.`)}let h=m.reduce((a,f)=>a+f.byteLength,0);return {bytes:i,metadata:{compression:d,cubeSize:t,format:"RGBA16F CubeUVReflectionMapping",height:l.pixelHeight,rawBytes:h,sha256:c(i),three:r,version:q,width:l.pixelWidth}}}a(oe,"encodeRoomEnvironmentKtx2");var S=class{static{a(this,"BakeInbox");}promise;#t=a(()=>{},"#resolve");#n=a(()=>{},"#reject");#e=false;constructor(){this.promise=new Promise((n,t)=>{this.#t=n,this.#n=t;});}receive(n){return this.#e?false:(this.#e=true,this.#t(n),true)}reject(n){this.#e||(this.#e=true,this.#n(n));}};function ie(e){if(e.url!==void 0)try{return new URL(e.url,"http://three-blocks.invalid").pathname}catch{return}}a(ie,"requestPath");function y(e,n,t=""){e.statusCode=n,e.setHeader("Content-Type",t.startsWith("<!")?"text/html; charset=utf-8":"text/plain; charset=utf-8"),e.setHeader("Cache-Control","no-store"),e.end(t);}a(y,"respond");function ae(e,n){return {name:"three-blocks:environment-bake",enforce:"post",resolveId(t){return t===T?C:void 0},load(t){return t===C?n:void 0},configureServer(t){t.middlewares.use((r,o,m)=>{let d=ie(r);if(d===D&&(r.method==="GET"||r.method==="HEAD")){let a=r.method==="HEAD"?"":`<!doctype html><html lang="en"><head><meta charset="utf-8"><title>Three Blocks environment bake</title></head><body><canvas id="three-blocks-environment-baker" width="1" height="1"></canvas><script type="module" src="${Y}"></script></body></html>`;y(o,200,a);return}if(d!==J)return m();if(r.method!=="POST"){y(o,405,"POST required");return}let c=r.headers["content-type"];if(typeof c!="string"||!c.toLowerCase().startsWith("image/ktx2")){y(o,415,"image/ktx2 required");return}let u=Number(r.headers["content-length"]??0);if(Number.isFinite(u)&&u>_){y(o,413,"Bake payload exceeds 128 MiB");return}let i=[],l=0,h=false;r.on("data",a=>{l+=a.byteLength,l>_?h=true:i.push(a);}),r.on("error",a=>e.reject(a)),r.on("end",()=>{if(h){y(o,413,"Bake payload exceeds 128 MiB"),e.reject(new Error("RoomEnvironment bake upload exceeded 128 MiB."));return}let a=r.headers["x-three-revision"];if(typeof a!="string"){y(o,400,"x-three-revision required"),e.reject(new Error("RoomEnvironment upload omitted the Three.js revision."));return}let f=e.receive({bytes:new Uint8Array(Buffer.concat(i)),threeRevision:a});y(o,f?204:409,f?"":"Bake upload already received");});});}}}a(ae,"bakePlugin");async function se(){let e=p.dirname(fileURLToPath(import.meta.url)),n=[p.join(e,"browser","environment-bake.js"),p.join(e,"browser","environment-bake.ts")];for(let t of n)if(await d(t))return (await h(t,a$1.semanticInput,"Environment bake browser entry")).data.toString("utf8");throw new Error("The separately built environment bake browser entry is missing.")}a(se,"browserEntrySource");function de(e){return new Promise((n,t)=>{e.on("pageerror",r=>{b(r.message)||t(r);}),e.on("console",r=>{r.type()==="error"&&!b(r.text())&&t(new Error(r.text()));});})}a(de,"pageFailure");async function ue(e,n){await e.waitForFunction(()=>globalThis.__THREE_BLOCKS_ROOM_ENVIRONMENT_BAKE__!==void 0,void 0,{timeout:Math.min(n,3e4)});let t=await e.evaluate(()=>globalThis.__THREE_BLOCKS_ROOM_ENVIRONMENT_BAKE__);if(!t||typeof t!="object"||Reflect.get(t,"ok")!==true){let r=t&&typeof t=="object"?Reflect.get(t,"error"):void 0;throw new Error(typeof r=="string"?r:"Browser RoomEnvironment bake did not report success.")}}a(ue,"readBrowserBakeResult");var me=a(async e=>{let{createServer:n}=await import('vite'),t=new S,r,o,m,d,c=false;try{let u=await se();r=await n({root:e.root,configFile:!1,logLevel:"silent",optimizeDeps:{noDiscovery:!0},plugins:[ae(t,u)],server:{host:"127.0.0.1",port:0,strictPort:!1}}),await r.listen();let i=r.httpServer?.address();if(!i||typeof i=="string")throw new Error("Environment bake Vite server has no ephemeral TCP address.");o=await launchNodeRenderer(),m=await o.newContext({viewport:{width:320,height:240}});let l=await m.newPage(),h=de(l),a=new Promise((g,E)=>{d=setTimeout(()=>E(new Error(`RoomEnvironment bake timed out after ${e.timeoutMs}ms.`)),e.timeoutMs),d.unref();});await l.goto(`http://127.0.0.1:${i.port}${D}?size=${e.size}`,{waitUntil:"domcontentloaded",timeout:Math.min(e.timeoutMs,3e4)});let f=await Promise.race([t.promise,h,a]);return await ue(l,e.timeoutMs),f}catch(u){throw c=true,t.reject(u instanceof Error?u:new Error(String(u))),await t.promise.catch(()=>{}),u}finally{d&&clearTimeout(d);let u=[];if(await m?.close().catch(i=>u.push(`context: ${i instanceof Error?i.message:String(i)}`)),await o?.close().catch(i=>u.push(`browser: ${i instanceof Error?i.message:String(i)}`)),await r?.close().catch(i=>u.push(`Vite: ${i instanceof Error?i.message:String(i)}`)),!c&&u.length>0)throw new Error(`RoomEnvironment cleanup failed (${u.join("; ")}).`)}},"captureRoomEnvironment");function ce(e$1,n){let t=n??Q;if(p.isAbsolute(t)||t.length===0||t.length>2048||/[\u0000-\u001f\u007f]/u.test(t)||!t.endsWith(".ktx2"))throw new Error("Environment output must be a bounded project-relative .ktx2 path.");let r=p.resolve(e$1,t);if(!e(e$1,r)||r===e$1)throw new Error("Environment output escapes the project root.");return {asset:r,metadata:`${r.slice(0,-5)}.json`}}a(ce,"outputPaths");async function le(e$1,n){let t=p.relative(e$1,n);if(t==="")return;let r=e$1;for(let m of t.split(p.sep)){r=p.join(r,m),await d(r)||await mkdir(r);let d$1=await lstat(r);if(d$1.isSymbolicLink()||!d$1.isDirectory())throw new Error(`Environment output parent is not a real directory: ${r}.`)}let o=await realpath(n);if(!e(e$1,o))throw new Error("Environment output parent resolves outside the project root.")}a(le,"ensureSafeParent");async function $(e){if(!await d(e))return;let n=await lstat(e);if(n.isSymbolicLink()||!n.isFile())throw new Error(`Environment output target must be a regular file: ${e}.`)}a($,"validateOutputTarget");async function fe(e,n,t,r){await Promise.all([$(e),$(t)]);let o=`${process.pid}-${randomUUID()}`,m=p.join(p.dirname(e),`.${p.basename(e)}.${o}.tmp`),d$1=p.join(p.dirname(t),`.${p.basename(t)}.${o}.tmp`),c=`${m}.backup`,u=`${d$1}.backup`,i=false,l=false,h=false,a=false;try{await Promise.all([writeFile(m,n,{flag:"wx"}),writeFile(d$1,r,{encoding:"utf8",flag:"wx"})]),await d(e)&&(await rename(e,c),i=!0),await d(t)&&(await rename(t,u),l=!0),await rename(m,e),h=!0,await rename(d$1,t),a=!0,await Promise.all([rm(c,{force:!0}),rm(u,{force:!0})]);}catch(f){throw a&&await rm(t,{force:true}),h&&await rm(e,{force:true}),l&&await rename(u,t),i&&await rename(c,e),f}finally{await Promise.all([rm(m,{force:true}),rm(d$1,{force:true}),rm(c,{force:true}),rm(u,{force:true})]);}}a(fe,"writeAtomicPair");function O(e,n){return p.relative(e,n).split(p.sep).join("/")}a(O,"portableRelative");async function xe(e){let n=await realpath(e.root),t=P(e.size??256),r=N(e.timeoutMs,"Environment bake timeoutMs",1e3,15*6e4,24e4),o=ce(n,e.output);await le(n,p.dirname(o.asset));let d=await(e.capture??me)({root:n,size:t,timeoutMs:r,headed:e.headed===true}),c$1=oe(d.bytes,{cubeSize:t,threeRevision:d.threeRevision,compression:e.compression??"zstd"}),u=`${JSON.stringify(c$1.metadata,null,2)}
2
+ `;await fe(o.asset,c$1.bytes,o.metadata,u);let i=await readFile(o.asset);if(c(i)!==c$1.metadata.sha256)throw new Error("Committed RoomEnvironment checksum does not match metadata.");return {schemaVersion:1,command:"environment bake",output:O(n,o.asset),metadataOutput:O(n,o.metadata),bytes:c$1.bytes.byteLength,metadata:c$1.metadata}}a(xe,"bakeRoomEnvironment");function pe(e){if(e<1e3)return `${e} B`;let n=e/1e3;return `${n>=100?Math.round(n):n.toFixed(1)} kB`}a(pe,"formatBytes");function Be(e){return [`\u2713 Environment ${e.metadata.width}\xD7${e.metadata.height} \xB7 CubeUV ${e.metadata.cubeSize}px \xB7 RGBA16F ${e.metadata.compression}`,` Output ${e.output} \xB7 ${pe(e.bytes)}`,` Checksum ${e.metadata.sha256}`].join(`
3
+ `)}a(Be,"formatEnvironmentBakeReport");export{P as a,oe as b,me as c,xe as d,Be as e};
@@ -0,0 +1,80 @@
1
+ import {b as b$1}from'./chunk-ZG3LO3VB.js';import {f,g,c,a as a$4}from'./chunk-4SVF5BRM.js';import {a as a$3,b}from'./chunk-NDIPQLTU.js';import {a as a$2}from'./chunk-WNSGAV6N.js';import {a,k,j as j$1,e,d}from'./chunk-ECQE4D2U.js';import {a as a$1}from'./chunk-7X4DHW36.js';import x from'process';import {createServer}from'http';import {createRequire}from'module';import {lstat,realpath}from'fs/promises';import j from'path';import {pathToFileURL}from'url';var Z="three-blocks.shader-capture.runtime.v1";var ge="/__three-blocks/shaders/capture",J="/__three-blocks/shaders/telemetry",Se="/__three-blocks/shaders/runtime.js",be="/__three-blocks/shaders/bootstrap.js",ve="/__three-blocks/shaders/bridge.js",Re=a.manifest*2,re=/^[a-z0-9][a-z0-9_-]{0,63}$/u,Te=64,ke=3e4;async function Le(n){let e;try{e=createRequire(j.join(n,"package.json")).resolve("vite");}catch(r){throw new Error("Shader capture requires Vite in the target project.",{cause:r})}let t=await import(pathToFileURL(e).href);if(typeof t.createServer!="function")throw new Error(`The target project's Vite entry does not export createServer(): ${e}`);return t.createServer}a$1(Le,"loadProjectCreateServer");var ne=class{static{a$1(this,"CaptureInbox");}#e=new Map;#t=new Map;wait(e,t){let r=this.#t.get(e);if(r!==void 0)return this.#t.delete(e),Promise.resolve(r);if(this.#e.has(e))throw new Error(`A shader capture is already waiting for scene "${e}".`);return new Promise((a,s)=>{let o=setTimeout(()=>{this.#e.delete(e),s(new Error(`Shader capture "${e}" timed out after ${t}ms.`));},t);this.#e.set(e,{resolve:a,reject:s,timer:o});})}receive(e){if(!a$2(e)||typeof e.scene!="string"||!re.test(e.scene))throw new Error("Capture POST has no safe scene key.");if(!this.#t.has(e.scene)&&!this.#e.has(e.scene)&&this.#t.size>=Te)throw new Error("Capture POST exceeds the scene inbox limit.");let t=this.#e.get(e.scene);t?(clearTimeout(t.timer),this.#e.delete(e.scene),t.resolve(e)):this.#t.set(e.scene,e);}cancel(e,t){let r=this.#e.get(e);r&&(clearTimeout(r.timer),this.#e.delete(e),r.reject(t));}rejectAll(e){for(let t of this.#e.values())clearTimeout(t.timer),t.reject(e);this.#e.clear(),this.#t.clear();}};async function Fe(n,e){let t=await Promise.race([e.then(r=>({kind:"capture",value:r})),n.then(()=>({kind:"navigation"}))]);return t.kind==="capture"?t.value:e}a$1(Fe,"waitForShaderCaptureAcrossNavigation");var ae=class{static{a$1(this,"TelemetryHub");}#e=new Map;#t=new Map;markFirstRequest(e){re.test(e)&&!this.#t.has(e)&&this.#t.set(e,Date.now());}firstRequest(e){return this.#t.get(e)}receive(e){if(!a$2(e)||typeof e.scene!="string"||!re.test(e.scene))throw new Error("Shader telemetry has no bounded scene key.");if(!this.#e.has(e.scene)&&this.#e.size>=Te)throw new Error("Shader telemetry exceeds the scene limit.");this.#e.set(e.scene,e);}read(e){return this.#e.get(e)}clear(e){this.#e.delete(e),this.#t.delete(e);}},$e=a$1(async(n,e,t,r,a)=>{let s=0;for(;n.__threeBlocksParityUsesAnimationLoop!==true&&s<e;)await r(),s+=1;if(n.__threeBlocksParityUsesAnimationLoop===true){let o=Number(n.__threeBlocksParityCompletedFrame||0),i=Number(t),d=Number.isSafeInteger(i)&&i>=o?i:o+e;for(n.__threeBlocksParityTargetFrame=d;Number(n.__threeBlocksParityCompletedFrame||0)<d;)await r();}return await a(),Number(n.__threeBlocksParityCompletedFrame||0)},"settleShaderParityFrames");function oe(n,e){return `(() => {
2
+ const root = globalThis;
3
+ const scene = new URL(location.href).searchParams.get('captureId')
4
+ || 'default';
5
+ const workerCapture = ${JSON.stringify(e??null).replaceAll("<","\\u003c")};
6
+ if (workerCapture) root[Symbol.for('three-blocks.shader-capture.worker-activation.v1')] = { ...workerCapture, scene };
7
+ const randomSeed = (value) => {
8
+ let state = 2166136261;
9
+ for (let index = 0; index < value.length; index++) state = Math.imul(state ^ value.charCodeAt(index), 16777619) >>> 0;
10
+ return state === 0 ? 0x9e3779b9 : state;
11
+ };
12
+ const advanceRandom = (state) => {
13
+ state ^= state << 13;
14
+ state ^= state >>> 17;
15
+ state ^= state << 5;
16
+ return state >>> 0;
17
+ };
18
+ const parityMode = new URL(location.href).searchParams.get('threeBlocksShaderMode');
19
+ if (parityMode === 'live' || parityMode === 'precompiled') {
20
+ root.__threeBlocksParityEpoch = 1700000000000;
21
+ root.__threeBlocksParityTime = 0;
22
+ Date.now = () => root.__threeBlocksParityEpoch + Number(root.__threeBlocksParityTime || 0);
23
+ }
24
+ const randomStreams = new Map();
25
+ Math.random = () => {
26
+ const stackLine = String(new Error().stack || '').split('\\n')[2] || 'unknown';
27
+ const originIndex = stackLine.indexOf(location.origin);
28
+ const callsite = (originIndex >= 0 ? stackLine.slice(0, originIndex) : stackLine).trim() || 'anonymous';
29
+ const next = advanceRandom(randomStreams.get(callsite) ?? randomSeed(scene + '|' + callsite));
30
+ randomStreams.set(callsite, next);
31
+ return next / 4294967296;
32
+ };
33
+ const readiness = { workerReady: false, assetsReady: false, textReady: false, compileEnd: false, firstFrame: false };
34
+ const stats = { buildCalls: 0, renderBuilds: 0, computeBuilds: 0, registeredBuilds: 0, registeredRenderBuilds: 0, registeredComputeBuilds: 0, buildMs: 0, syncBuildMs: 0, asyncBuildElapsedMs: 0, precompiledSetupMs: 0, maxSyncBuildMs: 0, maxPrecompiledSetupMs: 0, hydrationMs: 0, maxHydrationMs: 0, injected: 0, injectedRender: 0, injectedCompute: 0, missed: 0, missedRender: 0, missedCompute: 0, missedKeys: [] };
35
+ const settleParityFrames = ${$e.toString()};
36
+ const settle = (frames, requestedTarget) => settleParityFrames(
37
+ root,
38
+ frames,
39
+ requestedTarget,
40
+ () => new Promise((resolve) => requestAnimationFrame(resolve)),
41
+ () => new Promise((resolve) => setTimeout(resolve, 100)),
42
+ );
43
+ const bridge = { protocolVersion: 1, compatibility: ${JSON.stringify(n)}, transform: ${b}, readiness, stats, settle };
44
+ root.__threeBlocksShaderTools = bridge;
45
+ requestAnimationFrame(() => requestAnimationFrame(() => { readiness.firstFrame = true; }));
46
+ const poll = async () => {
47
+ try {
48
+ const response = await fetch('/__three-blocks/shaders/telemetry?scene=' + encodeURIComponent(scene), { cache: 'no-store' });
49
+ if (response.status !== 204 && response.ok) {
50
+ const payload = await response.json();
51
+ if (payload.protocolVersion !== 1 || payload.compatibility !== bridge.compatibility || payload.transform !== bridge.transform) throw new Error('incompatible shader telemetry');
52
+ Object.assign(stats, payload.stats);
53
+ if (Array.isArray(payload.demands)) bridge.demands = payload.demands;
54
+ if (typeof payload.demandTotal === 'number') bridge.demandTotal = payload.demandTotal;
55
+ readiness.workerReady = true;
56
+ if (payload.settled === true) {
57
+ readiness.assetsReady = true;
58
+ readiness.textReady = true;
59
+ readiness.compileEnd = true;
60
+ }
61
+ const smoke = root.__threeBlocksSmoke && typeof root.__threeBlocksSmoke === 'object' ? root.__threeBlocksSmoke : { protocolVersion: 1, worker: { offscreenCanvas: true, visible: true }, readiness: {} };
62
+ smoke.readiness = { ...(smoke.readiness || {}), ...readiness };
63
+ root.__threeBlocksSmoke = smoke;
64
+ }
65
+ } catch {}
66
+ setTimeout(poll, 40);
67
+ };
68
+ void poll();
69
+ })();`}a$1(oe,"publicBridgeScript");function Pe(n,e,t,r,a=false){let s=new URL(n.url??"/","http://three-blocks.invalid"),o=s.pathname;if(a&&n.method==="GET"&&/^\/three-blocks\/shaders\/[a-z0-9][a-z0-9_-]{0,63}\.(?:webgpu|webgl)\.json$/u.test(o))return e.statusCode=204,e.end(),true;if(o===J&&n.method==="GET"){let h=s.searchParams.get("scene")??"",S=r.read(h);return S===void 0?(e.statusCode=204,e.end()):(e.statusCode=200,e.setHeader("Content-Type","application/json"),e.end(JSON.stringify(S))),true}let i=o===ge,d=o===J;if(!i&&!d)return false;if(n.method!=="POST")return e.statusCode=405,e.end("POST required"),true;let l=[],f=0,p=false;return n.on("data",h=>{f+=h.byteLength,f>Re?p=true:l.push(h);}),n.on("end",()=>{if(p){e.statusCode=413,e.end("capture payload too large");return}try{let h=JSON.parse(Buffer.concat(l).toString("utf8"));d?r.receive(h):t.receive(h),e.statusCode=204,e.end();}catch(h){e.statusCode=400,e.end(h instanceof Error?h.message:String(h));}}),true}a$1(Pe,"handleCaptureEndpoint");function Ne(n,e,t,r,a){return {name:"three-blocks:shader-capture-endpoint",transformIndexHtml(){return [{tag:"script",children:oe(r,a),injectTo:"head-prepend"}]},configureServer(s){s.middlewares.use((o,i,d)=>{let f=new URL(o.url??"/","http://three-blocks.invalid").searchParams.get("captureId");f!==null&&e.markFirstRequest(f),!Pe(o,i,n,e,t)&&d();});}}}a$1(Ne,"captureEndpointPlugin");function fe(n,e,t){let r=new URL(e.url,n);for(let[a,s]of Object.entries(t))r.searchParams.set(a,s);return r.href}a$1(fe,"browserUrl");function Ie(n,e,t){let r=new URL(e.url,n);for(let a of ["capture","precompiled"])r.searchParams.delete(a);return r.searchParams.set("captureId",e.key),r.searchParams.set("threeBlocksShaderCapture","1"),r.searchParams.set("threeBlocksShaderMode","precompiled"),t==="webgl"&&r.searchParams.set("webgl","1"),r.searchParams.set("tbStats","1"),r.href}a$1(Ie,"publishedBrowserUrl");async function O(n){let e;try{await Promise.race([n(),new Promise(t=>{e=setTimeout(t,ke);})]);}catch{}finally{e&&clearTimeout(e);}}a$1(O,"closeBrowserResource");async function G(n){let e;try{return await Promise.race([n().catch(()=>null),new Promise(t=>{e=setTimeout(()=>t(null),ke);})])}finally{e!==void 0&&clearTimeout(e);}}a$1(G,"readPageDiagnostic");function ee(n){let e=a$1(()=>{},"resolveFirst"),t=new Promise(l=>{e=l;}),r=a$1(()=>{},"removeBrowserListener"),a={console:[],page:[],first:t,dispose:a$1(()=>r(),"dispose")},s=false,o=a$1(l=>{s||(s=true,e(new Error(l)));},"report"),i=n.context().browser(),d=a$1(()=>o("Shader browser disconnected before observation completed."),"onDisconnected");return i?.on("disconnected",d),r=a$1(()=>{i?.off("disconnected",d);},"removeBrowserListener"),n.on("console",l=>{let f=l.type()==="warning"&&/\[three-blocks\/shaders\].*(?:has no entry|manifest miss|hydration)/iu.test(l.text());if(l.type()!=="error"&&!f||b$1(l.text()))return;let p=l.location().url,h=p.length>0?`${l.text()} (${p})`:l.text();a.console.push(h),o(`Browser console ${f?"warning":"error"}: ${h}`);}),n.on("pageerror",l=>{if(b$1(l.message))return;let f=l.stack||l.message;a.page.push(f),o(`Browser page error: ${f}`);}),n.on("crash",()=>o("Browser page crashed before shader capture completed.")),n.on("close",()=>o("Browser page closed before shader capture completed.")),a}a$1(ee,"collectErrors");function F(n,e,t=false){return typeof n[e]=="boolean"?n[e]:t}a$1(F,"booleanField");function Ue(n){if(!a$2(n))throw new Error("Browser shader stats are unavailable.");let e=a$1((t,r=true)=>{let a=n[t];if(typeof a!="number"||!Number.isFinite(a)||a<0||r&&!Number.isSafeInteger(a))throw new Error(`Browser shader stats.${t} is invalid.`);return a},"read");return {buildCalls:e("buildCalls"),renderBuilds:e("renderBuilds"),computeBuilds:e("computeBuilds"),registeredBuilds:e("registeredBuilds"),registeredRenderBuilds:e("registeredRenderBuilds"),registeredComputeBuilds:e("registeredComputeBuilds"),buildMs:e("buildMs",false),syncBuildMs:e("syncBuildMs",false),asyncBuildElapsedMs:e("asyncBuildElapsedMs",false),precompiledSetupMs:e("precompiledSetupMs",false),maxSyncBuildMs:e("maxSyncBuildMs",false),maxPrecompiledSetupMs:e("maxPrecompiledSetupMs",false),hydrationMs:e("hydrationMs",false),maxHydrationMs:e("maxHydrationMs",false),injected:e("injected"),injectedRender:e("injectedRender"),injectedCompute:e("injectedCompute"),missed:e("missed"),missedRender:e("missedRender"),missedCompute:e("missedCompute"),...Array.isArray(n.missedKeys)&&n.missedKeys.every(t=>typeof t=="string")?{missedKeys:n.missedKeys}:{}}}a$1(Ue,"parseStats");function H(n,e,t,r,a){if(!a$2(n))throw new Error("The page did not expose the public shader devtools bridge.");if(!t&&n.protocolVersion!==1)throw new Error(`Scene "${e.key}" exposed an unsupported shader bridge protocol.`);let s=n.readiness;if(!a$2(s))throw new Error("The shader bridge readiness snapshot is invalid.");let o={workerReady:F(s,"workerReady"),assetsReady:F(s,"assetsReady"),textReady:e.requiresText?F(s,"textReady"):true,compileEnd:F(s,"compileEnd"),firstFrame:F(s,"firstFrame",t)};if(!o.workerReady||!o.assetsReady||!o.textReady||!o.compileEnd)throw new Error(`Scene "${e.key}" did not reach worker/assets/text/compile readiness.`);let i=t?a:n.compatibility,d=t?b:n.transform;if(i!==a||d!==b)throw new Error(`Scene "${e.key}" exposed incompatible shader bridge metadata.`);g(r);let l=Array.isArray(n.demands)?n.demands.filter(a$2).slice(0,64):void 0;return {compatibility:a,transform:d,readiness:o,stats:Ue(n.stats),...l===void 0?{}:{demands:l}}}a$1(H,"parseBridge");async function V(n,e){return n.evaluate(t=>{let r=globalThis;if(!t)return r.__threeBlocksShaderTools??null;let a=r.__threeBlocks,s=r.__threeBlocksTslStats;if(!a||typeof a!="object")return null;let o=a;return {readiness:{workerReady:o.workerReady===true,assetsReady:o.loadEnd===true||o.assetsReady===true,textReady:o.textReady===true,compileEnd:o.compileEnd===true,firstFrame:true},stats:s}},e)}a$1(V,"readBridge");async function Ee(n,e){let t=await G(()=>n.evaluate(r=>{let a=globalThis,s=a$1(i=>{let d=a;for(let l of i.split(".")){if(d===null||typeof d!="object"&&typeof d!="function")return;d=Reflect.get(d,l);}return d},"resolveGlobal"),o=null;if(r!==null)try{o=JSON.stringify(s(`${r}Diagnostics`))??null;}catch{o=null;}return JSON.stringify({parityCompletedFrame:Number(a.__threeBlocksParityCompletedFrame??0),diagnostics:o})},e??null));return t===null?{alive:false,signature:""}:{alive:true,signature:t}}a$1(Ee,"probePageProgress");async function $(n,e,t,r){let a=n.evaluate(async l=>{let p=globalThis.__threeBlocksShaderTools;if(p&&typeof p=="object"){let g=Reflect.get(p,"settle");if(typeof g=="function"){let u=await g(l.frames,l.targetFrame);return typeof u=="number"&&Number.isSafeInteger(u)?u:0}}if(!l.legacy||!l.modulePath)throw new Error("The public shader bridge does not provide deterministic settle().");let h=await import(l.modulePath);if(!h.store||typeof h.store!="object")throw new Error("Legacy deterministic store is unavailable.");let S=h.store;return S.recordFrameCount=0,S.recordFrameRate=60,S.recordTotalFrames=l.frames,S.recording=true,await new Promise((g,u)=>{let w=Date.now(),m=a$1(()=>{if(S.recording===false)return g();if(Date.now()-w>l.timeoutMs)return u(new Error("Legacy deterministic settle timed out."));setTimeout(m,25);},"poll");m();}),0},{frames:t,targetFrame:r,legacy:e.bridge.legacyLab,modulePath:e.bridge.deterministicModule??null,timeoutMs:e.timeoutMs}),s=D(e),o=false,i,d=(async()=>{let l=Date.now(),f=l,p="";for(;;){let h=s-(Date.now()-l);if(h<=0)throw new Error(`Shader parity settle timed out after ${s}ms.`);let S=e.timeoutMs-(Date.now()-f);if(S<=0){let g=await Ee(n,e.readiness.global);if(o)throw new Error("Shader parity settle already resolved.");if(g.alive&&g.signature===p)throw new Error(`Shader parity settle timed out after ${e.timeoutMs}ms without progress (hard cap ${s}ms).`);p=g.signature,f=Date.now();continue}if(await new Promise(g=>{i=setTimeout(g,Math.min(S,h,2500));}),o)throw new Error("Shader parity settle already resolved.")}})();try{return await Promise.race([a,d])}finally{o=true,i!==void 0&&clearTimeout(i),d.catch(()=>{});}}a$1($,"settlePage");async function pe(n,e,t){e.readiness.selector===void 0&&e.readiness.global===void 0||await Promise.race([n.waitForFunction(r=>{let a=globalThis;if(r.selector!==void 0&&a.document?.querySelector(r.selector)==null)return false;if(r.global===void 0)return true;let s=a;for(let d of r.global.split(".")){if((typeof s!="object"||s===null)&&typeof s!="function")return false;s=Reflect.get(s,d);}if(s===true)return true;if(typeof s!="object"||s===null||typeof Reflect.get(s,"then")!="function")return false;let o=a.__threeBlocksReadinessState,i=o instanceof Map?o:new Map;return o instanceof Map||(a.__threeBlocksReadinessState=i),i.has(s)||(i.set(s,false),Promise.resolve(s).then(()=>i.set(s,true),()=>i.set(s,false))),i.get(s)===true},e.readiness,{timeout:D(e)}),t.first.then(r=>Promise.reject(r))]);}a$1(pe,"waitForConfiguredReadiness");async function we(n){let e=n.locator("canvas"),r=(await e.evaluateAll(a=>a.map((s,o)=>{let i=s.getBoundingClientRect();return {index:o,area:Math.max(0,i.width)*Math.max(0,i.height)}}))).sort((a,s)=>s.area-a.area)[0];if(r===void 0||r.area<=0)throw new Error("Published page has no visible renderer canvas.");return Buffer.from(await e.nth(r.index).screenshot({type:"png"}))}a$1(we,"primaryCanvasScreenshot");async function te(n,e,t,r,a,s,o){let i=K(r,a,s),d=await c(),l=`(() => {
70
+ const runtime = globalThis[Symbol.for(${JSON.stringify(Z)})];
71
+ if (!runtime || typeof runtime.configureThreeBlocksShaderCapture !== 'function') {
72
+ throw new Error('@three-blocks/devtools attached shader capture runtime is incompatible.');
73
+ }
74
+ runtime.configureThreeBlocksShaderCapture(${JSON.stringify(i).replaceAll("<","\\u003c")});
75
+ })();`;await n.addInitScript({content:`${d}
76
+ ${l}`}),await n.addInitScript({content:oe(o,i)}),await n.route("**/*",async f=>{let p=f.request(),h=new URL(p.url()),S=h.pathname;if(p.method()==="GET"&&r!=="precompiled"&&/^\/three-blocks\/shaders\/[a-z0-9][a-z0-9_-]{0,63}\.(?:webgpu|webgl)\.json$/u.test(S)){await f.fulfill({status:204});return}if(S===J&&p.method()==="GET"){let w=t.read(h.searchParams.get("scene")??"");await f.fulfill(w===void 0?{status:204}:{status:200,contentType:"application/json",body:JSON.stringify(w)});return}let g=S===ge,u=S===J;if((g||u)&&p.method()==="POST"){let w=p.postDataBuffer()??Buffer.alloc(0);if(w.byteLength>Re){await f.fulfill({status:413,body:"capture payload too large"});return}try{let m=JSON.parse(w.toString("utf8"));u?t.receive(m):e.receive(m),await f.fulfill({status:204});}catch(m){await f.fulfill({status:400,body:m instanceof Error?m.message:String(m)});}return}await f.continue();});}a$1(te,"configureAttachedContext");var He=Object.freeze({".avif":"image/avif",".css":"text/css; charset=utf-8",".gif":"image/gif",".html":"text/html; charset=utf-8",".ico":"image/x-icon",".jpeg":"image/jpeg",".jpg":"image/jpeg",".js":"text/javascript; charset=utf-8",".json":"application/json; charset=utf-8",".mjs":"text/javascript; charset=utf-8",".mp4":"video/mp4",".png":"image/png",".svg":"image/svg+xml",".wasm":"application/wasm",".webm":"video/webm",".webp":"image/webp",".woff":"font/woff",".woff2":"font/woff2"});function Ve(n){let e=[`<script src="${ve}"></script>`,`<script type="module" src="${be}"></script>`].join(""),t=/<head(?:\s[^>]*)?>/iu.exec(n);return t===null?`${e}${n}`:`${n.slice(0,t.index+t[0].length)}${e}${n.slice(t.index+t[0].length)}`}a$1(Ve,"injectStaticShaderCaptureHtml");function Ge(n,e,t){let r=K(n,e,t);return [`import { configureThreeBlocksShaderCapture } from ${JSON.stringify(Se)};`,`configureThreeBlocksShaderCapture( ${JSON.stringify(r).replaceAll("<","\\u003c")} );`].join(`
77
+ `)}a$1(Ge,"staticCaptureBootstrap");var Je=5e3;function D(n){return Math.max(n.maxTimeoutMs??n.timeoutMs,n.timeoutMs)}a$1(D,"configuredHardCapMs");function K(n,e,t){return {capture:n==="capture",backend:t,driven:true,forceLive:n!=="precompiled",settleFrames:e.settleFrames,settleTimeoutMs:e.settleTimeoutMs??3e4,...n==="capture"?{deadlineAt:Date.now()+Math.max(1e3,D(e)-Je)}:{},readiness:e.readiness,transform:b}}a$1(K,"shaderCaptureConfiguration");async function Ke(n,e){let t=await k(n,e,o=>/\.(?:c|m)?js$/u.test(o),16384),r=false,a$1=false,s;for(let o of t){let i=(await j$1(n,o,a.texture,"Static application JavaScript")).data.toString("utf8");if(i.includes("nodeBuilderStateProvider")&&(r=true),i.includes("three-blocks.shader-capture.runtime.v1")&&(a$1=true,s??=o),r&&a$1)break}if(!r||!a$1)throw new Error("The static build does not contain the Three.js shader capture transform. Run `shaders capture` without an explicit driver or URL to preview adapter wiring and build automatically, or add the manual adapter from the package README and rebuild.");return {seen:true,applied:true,alreadyPresent:false,captureApplied:true,...s===void 0?{}:{id:s}}}a$1(Ke,"inspectStaticCaptureTransform");async function We(n,e$1){let t;try{t=decodeURIComponent(e$1);}catch{return}if(t.includes("\0"))return;let r=t.replace(/^\/+/u,""),a$1=j.resolve(n,r.length===0?"index.html":r);if(!e(n,a$1)||a$1===n||(await d(a$1)&&(await lstat(a$1)).isDirectory()&&(a$1=j.join(a$1,"index.html")),!await d(a$1)&&j.extname(a$1).length===0&&(a$1=j.join(n,"index.html")),!await d(a$1)))return;let s=await j$1(n,a$1,a.texture,"Static application asset");return {data:s.data,file:s.path}}a$1(We,"staticRequestFile");async function qe(n,e$1,t,r,a,s){let o=await realpath(n.root),i=await realpath(j.resolve(o,n.serve));if(!e(o,i)||i===o)throw new Error("--serve must name a built application directory inside the project root.");let d=await Ke(o,i),l=await a$4(),f=Ge(e$1,r,t),p=oe(a$3(n.runtime.three,t),K(e$1,r,t)),h=createServer((g,u)=>{(async()=>{if(Pe(g,u,a,s,e$1!=="precompiled"))return;let w=new URL(g.url??"/","http://three-blocks.invalid");if(g.method!=="GET"&&g.method!=="HEAD"){u.statusCode=405,u.end("GET or HEAD required");return}let m=w.pathname===Se?l:w.pathname===be?f:w.pathname===ve?p:void 0;if(m!==void 0){u.statusCode=200,u.setHeader("Content-Type","text/javascript; charset=utf-8"),u.setHeader("Cache-Control","no-store"),u.end(g.method==="HEAD"?void 0:m);return}let y=await We(i,w.pathname);if(y===void 0){u.statusCode=404,u.end("Not found");return}let v=j.extname(y.file).toLowerCase(),b=v===".html"?Buffer.from(Ve(y.data.toString("utf8"))):y.data;u.statusCode=200,u.setHeader("Content-Type",He[v]??"application/octet-stream"),u.setHeader("Content-Length",String(b.byteLength)),u.setHeader("Cache-Control","no-store"),u.end(g.method==="HEAD"?void 0:b);})().catch(w=>{if(u.headersSent)return u.destroy(w instanceof Error?w:void 0);u.statusCode=500,u.end(w instanceof Error?w.message:String(w));});});await new Promise((g,u)=>{h.once("error",u),h.listen(0,"127.0.0.1",()=>{h.off("error",u),g();});});let S=h.address();if(!S||typeof S=="string")throw new Error("Static capture server did not expose an ephemeral TCP address.");return {server:h,baseUrl:`http://127.0.0.1:${S.port}`,transform:d}}a$1(qe,"startStaticShaderServer");function ze(n,e,t){return n===e?true:t&&n!==void 0&&n!=="capture"&&e!=="capture"}a$1(ze,"canReuseShaderBrowserSession");function ye(n){let e=n instanceof Error?n.message:String(n);return e.includes("Execution context was destroyed")&&e.includes("navigation")||/^launch: Timeout \d+ms exceeded\./u.test(e)||e.includes("Shader browser disconnected before observation completed.")}a$1(ye,"isRetryableShaderObservationNavigation");var A=class{static{a$1(this,"NodeShaderDriver");}#e;#t=new ne;#n=new ae;#u;#h;#s;#i;#r;#a;#m;#l;#f;#p;#c=0;constructor(e){this.#e=e;}#d(){return this.#u?.status??this.#h??{seen:false,applied:false,alreadyPresent:false}}async#w(e,t){if(this.#r?.isConnected()===true)return;let{launchNodeRenderer:r}=await import('@three-blocks/devtools/node');this.#r=await r(),this.#c=0;}async#o(e,t,r){let a;try{return await Promise.race([r(),new Promise((s,o)=>{a=setTimeout(()=>o(new Error(`launch: Timeout ${t.timeoutMs}ms exceeded.`)),t.timeoutMs);})])}catch(s){throw this.#r===e&&(this.#r=void 0),await O(()=>e.close()),s}finally{a!==void 0&&clearTimeout(a);}}async#y(e,t,r){let a=this.#s!==void 0||this.#i!==void 0||this.#e.url!==void 0&&this.#a!==void 0,s=this.#f===t&&(this.#i!==void 0?this.#l===e:ze(this.#l,e,r.bridge.legacyLab));if(a&&s){this.#l=e,await this.#w(r,t);return}if(a&&await this.close(),this.#l=e,this.#f=t,this.#e.url!==void 0){let o=new URL(this.#e.url);if(!["http:","https:"].includes(o.protocol)||o.username||o.password||o.hash)throw new Error("Attached shader URL must be an HTTP(S) URL without credentials or a fragment.");this.#a=o.href,this.#h={seen:true,applied:true,alreadyPresent:false,captureApplied:true,id:"attached-application"},await this.#w(r,t);return}if(this.#e.serve!==void 0)try{let o=await qe({root:this.#e.root,runtime:this.#e.runtime,serve:this.#e.serve,...this.#e.headed===void 0?{}:{headed:this.#e.headed}},e,t,r,this.#t,this.#n);this.#i=o.server,this.#h=o.transform,this.#a=o.baseUrl,await this.#w(r,t);return}catch(o){throw await this.close(),o}this.#u=f(this.#e.runtime.three,{disableTimestampQueries:x.env.THREE_BLOCKS_SOFTWARE_WEBGPU==="1",...r.bridge.legacyLab?{}:{capture:{capture:e==="capture",driven:true,forceLive:e!=="precompiled",forceWebGL:t==="webgl",settleFrames:r.settleFrames,settleTimeoutMs:r.settleTimeoutMs??3e4,readiness:r.readiness}}}),this.#m={THREE_BLOCKS_SHADER_TOOL:x.env.THREE_BLOCKS_SHADER_TOOL,THREE_BLOCKS_PRECOMPILE_CAPTURE_SERVER:x.env.THREE_BLOCKS_PRECOMPILE_CAPTURE_SERVER},x.env.THREE_BLOCKS_SHADER_TOOL="1",x.env.THREE_BLOCKS_PRECOMPILE_CAPTURE_SERVER="1";try{let o=await Le(this.#e.root);this.#s=await o({root:this.#e.root,logLevel:"error",plugins:[this.#u.plugin,Ne(this.#t,this.#n,e!=="precompiled",a$3(this.#e.runtime.three,t),K(e,r,t))],server:{host:"127.0.0.1",port:0}}),await this.#s.listen();let i=this.#s.httpServer?.address();if(!i||typeof i=="string")throw new Error("Vite did not expose an ephemeral TCP address.");this.#a=`http://127.0.0.1:${i.port}`,await this.#w(r,t);}catch(o){throw await this.close(),o}}async capture(e,t,r="webgpu"){let a=Date.now();if(await this.#y("capture",r,t),!this.#r||!this.#a)throw new Error("Shader browser driver did not start.");let s=this.#r,o=await this.#o(s,t,()=>s.newContext({viewport:t.viewport,frameIntervalMs:1e3/60}));this.#e.url!==void 0&&await this.#o(s,t,()=>te(o,this.#t,this.#n,"capture",t,r,a$3(this.#e.runtime.three,r)));let i=await this.#o(s,t,()=>o.newPage()),d=ee(i);this.#n.clear(e.key);let l=D(t),f=this.#t.wait(e.key,l),p=false;l>t.timeoutMs?(async()=>{let m=Math.min(5e3,Math.max(1e3,Math.round(t.timeoutMs/8))),y=Date.now(),v="",b="";for(;!p;){if(await new Promise(E=>setTimeout(E,m)),p)return;let T=this.#n.read(e.key),k=T===void 0?"":JSON.stringify(T);if(k!==v){v=k,y=Date.now();continue}if(Date.now()-y<t.timeoutMs)continue;let P=await Ee(i,t.readiness.global);if(p)return;if(!P.alive||P.signature!==b){b=P.signature,y=Date.now();continue}this.#t.cancel(e.key,new Error(`Shader capture "${e.key}" timed out after ${t.timeoutMs}ms without progress (hard cap ${l}ms).`));return}})().catch(()=>{}):void 0;let S=Promise.race([f,d.first.then(m=>Promise.reject(m))]),g$1=a$1(()=>{},"resolveDisconnected"),u=new Promise(m=>{g$1=m;}),w=a$1(()=>g$1(new Error("Shader capture browser disconnected before posting a manifest.")),"onDisconnected");s.on("disconnected",w);try{let m=i.goto(fe(this.#a,e,{threeBlocksShaderCapture:"1",capture:"1",captureId:e.key,captureFrames:String(Math.max(4,t.settleFrames)),settleFrames:String(t.settleFrames),...r==="webgl"?{webgl:"1"}:{}}),{waitUntil:"domcontentloaded",timeout:t.timeoutMs}),y=await Fe(m,Promise.race([S,u.then(b=>Promise.reject(b))]));g(this.#d());let v=[...d.page,...d.console];if(v.length>0)throw new Error(`Capture browser errors:
78
+ - ${v.join(`
79
+ - `)}`);return a$2(y)?{...y,timing:{...a$2(y.timing)?y.timing:{},launch:a,...this.#n.firstRequest(e.key)===void 0?{}:{firstRequest:this.#n.firstRequest(e.key)},posted:Date.now()}}:y}catch(m){let y=m instanceof Error?m:new Error(String(m));this.#t.cancel(e.key,y),await f.catch(()=>{});let v=this.#n.read(e.key);if(y.message.includes("timed out")){let b=await G(()=>i.evaluate(P=>{let E=globalThis,W=E.__threeBlocksShaderTools,Ce=W&&typeof W=="object"?W:void 0,Be=E.document,M=Reflect.get(E,Symbol.for("three-blocks.shader-capture.cache-value.v1")),N=E.location,_e=N!==null&&typeof N=="object"&&typeof Reflect.get(N,"href")=="string"?String(Reflect.get(N,"href")):"http://three-blocks.invalid/",xe=new URL(_e).searchParams.get("captureId")??"default",se=M!==null&&typeof M=="object"&&typeof Reflect.get(M,"registrations")=="function"?Reflect.apply(Reflect.get(M,"registrations"),M,[xe]):void 0,ie=a$1(R=>{let _=E;for(let Me of R.split(".")){if(_===null||typeof _!="object"&&typeof _!="function")return;_=Reflect.get(_,Me);}return _},"resolveGlobal"),de=null,q=null;if(P!==null){let R=ie(P);de=R===true||R===false?R:R===void 0?"absent":R!==null&&typeof R.then=="function"?"promise":typeof R;try{let _=JSON.stringify(ie(`${P}Diagnostics`));q=typeof _=="string"?_.slice(0,2048):null;}catch{q=null;}}return {documentReadyState:Be?.readyState??null,parityTargetFrame:Number(E.__threeBlocksParityTargetFrame??0),parityCompletedFrame:Number(E.__threeBlocksParityCompletedFrame??0),readiness:Ce?.readiness??null,readinessGlobal:de,readinessDiagnostics:q,captureCache:M!==null&&typeof M=="object"?{activeScene:Reflect.get(M,"activeScene")??null,registrations:Array.isArray(se)?se.slice(0,16).map(R=>R!==null&&typeof R=="object"?{key:Reflect.get(R,"key")??null,kind:Reflect.get(R,"kind")??null}:null):null}:null,threeRuntimeResources:performance.getEntriesByType("resource").map(R=>R.name).filter(R=>R.includes("three.webgpu"))}},t.readiness.global??null)),T=t.readiness.global!==void 0&&b!==null&&b.readinessGlobal!==true,k=b===null?"Capture page did not answer diagnostics before the deadline; its main thread was blocked or gone. ":T?`Application readiness "${t.readiness.global}" never completed (state: ${JSON.stringify(b.readinessGlobal)}${b.readinessDiagnostics===null?"":`, diagnostics: ${b.readinessDiagnostics}`}). `:"";throw new Error(`${k}${y.message} Last capture state for "${e.key}": ${JSON.stringify({page:b,telemetry:v??null,transform:this.#d()})}`)}throw y}finally{p=true,d.dispose(),s.off("disconnected",w),await O(()=>o.close()),this.#c++,(!s.isConnected()||this.#c>=(t.browserRelaunchScenes??8))&&(this.#r===s&&(this.#r=void 0),await O(()=>s.close()),this.#c=0);}}async observe(e,t,r,a,s="webgpu"){for(let o=0;o<2;o++)try{return await this.#g(e,s,t,r,a)}catch(i){if(o===0&&ye(i))continue;throw i}throw new Error(`Shader observation retry was exhausted for scene "${e.key}".`)}async#g(e,t,r,a,s){if(await this.#y(r,t,a),!this.#r||!this.#a)throw new Error("Shader browser driver did not start.");let o=this.#r,i=await this.#o(o,a,()=>o.newContext({viewport:a.viewport}));this.#e.url!==void 0&&await this.#o(o,a,()=>te(i,this.#t,this.#n,r,a,t,a$3(this.#e.runtime.three,t)));let d=await this.#o(o,a,()=>i.newPage()),l=ee(d);this.#n.clear(e.key);try{await d.goto(fe(this.#a,e,{threeBlocksShaderCapture:"1",threeBlocksShaderMode:r,tbOverlay:"0",captureId:e.key,...r==="live"?{precompiled:"0"}:{},...t==="webgl"?{webgl:"1"}:{}}),{waitUntil:"domcontentloaded",timeout:a.timeoutMs}),await Promise.race([d.waitForFunction(a.bridge.legacyLab?"globalThis.__threeBlocks?.compileEnd === true":"globalThis.__threeBlocksShaderTools?.readiness?.compileEnd === true",void 0,{timeout:D(a)}),l.first.then(u=>Promise.reject(u))]),H(await V(d,a.bridge.legacyLab),e,a.bridge.legacyLab,this.#d(),a$3(this.#e.runtime.three,t)),await pe(d,a,l),await Promise.race([d.waitForFunction(a.bridge.legacyLab?"true":"globalThis.__threeBlocksShaderTools?.readiness?.firstFrame === true",void 0,{timeout:D(a)}),l.first.then(u=>Promise.reject(u))]),await $(d,a,1);let f=Buffer.from(await d.screenshot({type:"png",timeout:a.timeoutMs})),p=e.parityFrames??a.parity.frames,h=await $(d,a,p,s),S=Buffer.from(await d.screenshot({type:"png",timeout:a.timeoutMs}));e.parityFrames!==void 0&&p<a.parity.frames&&await $(d,a,a.parity.frames-p);let g=H(await V(d,a.bridge.legacyLab),e,a.bridge.legacyLab,this.#d(),a$3(this.#e.runtime.three,t));return this.#p===void 0&&(this.#p=await d.evaluate(async u=>{if(u==="webgl"){let k=Reflect.get(globalThis,"document").createElement("canvas").getContext("webgl2"),P=k?.getExtension("WEBGL_debug_renderer_info");return {adapter:k&&P?String(k.getParameter(P.UNMASKED_RENDERER_WEBGL)):"WebGL adapter",platform:navigator.platform||navigator.userAgent}}let w=Reflect.get(navigator,"gpu"),m=typeof w=="object"&&w!==null?Reflect.get(w,"requestAdapter"):void 0,y=typeof m=="function"?await Reflect.apply(m,w,[]):void 0,v=typeof y=="object"&&y!==null?Reflect.get(y,"info"):void 0,b=["description","device","architecture","vendor"].flatMap(T=>{let k=typeof v=="object"&&v!==null?Reflect.get(v,T):void 0;return typeof k=="string"&&k.length>0?[k]:[]});return {adapter:[...new Set(b)].join(" \xB7 ")||"WebGPU adapter",platform:navigator.platform||navigator.userAgent}},t)),{scene:e.key,mode:r,execution:"node",...g,frame:h,firstFrameScreenshot:f,screenshot:S,errors:[...l.page,...l.console]}}catch(f){let p=f instanceof Error?f:new Error(String(f));if(/(?:timed?\s*out|timeout)/iu.test(p.message)){let u=this.#n.read(e.key),w=await G(()=>d.evaluate(()=>{let m=globalThis,y=m.__threeBlocksShaderTools,v=y&&typeof y=="object"?y:void 0;return {documentReadyState:m.document?.readyState??null,parityTargetFrame:Number(m.__threeBlocksParityTargetFrame??0),parityCompletedFrame:Number(m.__threeBlocksParityCompletedFrame??0),readiness:v?.readiness??null,threeRuntimeResources:performance.getEntriesByType("resource").map(T=>T.name).filter(T=>T.includes("three.webgpu"))}}));throw new Error(`${p.message} Last ${r} state for "${e.key}": ${JSON.stringify({page:w,telemetry:u??null})}`)}let h=this.#n.read(e.key),g=(a$2(h)&&Array.isArray(h.demands)&&h.demands.length>0?JSON.stringify(h.demands).slice(0,6e3):void 0)??await G(()=>d.evaluate(u=>{let w=globalThis,m=Reflect.get(w,Symbol.for(u)),y=m!==null&&typeof m=="object"?Reflect.get(m,"readThreeBlocksShaderDemands"):void 0,v=typeof y=="function"?Reflect.apply(y,m,[]):void 0,b=w.__threeBlocksShaderTools,T=Array.isArray(v)&&v.length>0?v:b&&typeof b=="object"?Reflect.get(b,"demands"):void 0;return Array.isArray(T)&&T.length>0?JSON.stringify(T).slice(0,6e3):null},Z));throw typeof g=="string"?new Error(`${p.message}
80
+ ${r} demands: ${g}`):p}finally{l.dispose(),await O(()=>i.close());}}async observePublished(e,t,r="webgpu"){for(let a=0;a<2;a++)try{return await this.#S(e,r,t)}catch(s){if(a===0&&ye(s))continue;throw s}throw new Error(`Published shader observation retry was exhausted for scene "${e.key}".`)}async#S(e,t,r){if(await this.#y("precompiled",t,r),!this.#r||!this.#a)throw new Error("Shader browser driver did not start.");let a=this.#r,s=await this.#o(a,r,()=>a.newContext({viewport:r.viewport}));this.#e.url!==void 0&&await this.#o(a,r,()=>te(s,this.#t,this.#n,"precompiled",r,t,a$3(this.#e.runtime.three,t)));let o=await this.#o(a,r,()=>s.newPage()),i=ee(o);this.#n.clear(e.key);try{await o.goto(Ie(this.#a,e,t),{waitUntil:"domcontentloaded",timeout:r.timeoutMs}),await Promise.race([o.waitForFunction(r.bridge.legacyLab?"globalThis.__threeBlocks?.compileEnd === true":"globalThis.__threeBlocksShaderTools?.readiness?.compileEnd === true",void 0,{timeout:D(r)}),i.first.then(h=>Promise.reject(h))]),await pe(o,r,i),H(await V(o,r.bridge.legacyLab),e,r.bridge.legacyLab,this.#d(),a$3(this.#e.runtime.three,t)),await $(o,r,2);let d=await we(o),l=await $(o,r,120),f=await we(o),p=H(await V(o,r.bridge.legacyLab),e,r.bridge.legacyLab,this.#d(),a$3(this.#e.runtime.three,t));return {scene:e.key,mode:"precompiled",...p,frame:l,firstFrameScreenshot:d,beforeScreenshot:d,screenshot:f,errors:[...i.page,...i.console]}}finally{i.dispose(),await O(()=>s.close());}}timingEnvironment(){return this.#p??{adapter:`Node ${this.#f==="webgl"?"WebGL adapter":"WebGPU adapter"}`,platform:`${x.platform}/${x.arch}`}}async close(){this.#t.rejectAll(new Error("Shader browser driver closed.")),this.#r&&await O(()=>this.#r?.close()??Promise.resolve());let e=this.#s?.httpServer,t=e?Reflect.get(e,"closeAllConnections"):void 0;if(e&&typeof t=="function"&&Reflect.apply(t,e,[]),this.#s&&await O(()=>this.#s?.close()??Promise.resolve()),this.#i){let r=this.#i;r.closeAllConnections(),await O(()=>new Promise(a=>{r.close(()=>a());}));}if(this.#r=void 0,this.#s=void 0,this.#i=void 0,this.#a=void 0,this.#u=void 0,this.#h=void 0,this.#l=void 0,this.#f=void 0,this.#p=void 0,this.#c=0,this.#m){for(let[r,a]of Object.entries(this.#m))a===void 0?delete x.env[r]:x.env[r]=a;this.#m=void 0;}}};function ct(n){return new A(n)}a$1(ct,"createPlaywrightShaderDriver");function ut(n){return new A(n)}a$1(ut,"createStaticPlaywrightShaderDriver");function ht(n){return new A(n)}a$1(ht,"createAttachedPlaywrightShaderDriver");function mt(n){return new A(n)}a$1(mt,"createShaderDriver");export{Fe as a,$e as b,oe as c,ze as d,ye as e,ct as f,ut as g,ht as h,mt as i};