@three-blocks/devtools 11.1.0 → 12.0.0-alpha.399.g24d19fd0f1a1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +6 -2
  3. package/dist/{asset-optimize-YJGWKD4Y.js → asset-optimize-AC3RBHSK.js} +1 -1
  4. package/dist/browser/shader-capture.js +2 -2
  5. package/dist/browser-smoke-ZHNB3MIO.js +1 -0
  6. package/dist/{chunk-BBODS5RH.js → chunk-2SGYUV6P.js} +1 -1
  7. package/dist/chunk-75JSWKB4.js +2 -0
  8. package/dist/chunk-7YWPJCDF.cjs +1 -0
  9. package/dist/chunk-EX34XRLW.js +78 -0
  10. package/dist/chunk-HIS44NIG.js +23 -0
  11. package/dist/chunk-RITS37ER.js +1 -0
  12. package/dist/{chunk-S5LI2C2H.js → chunk-SNPGWQMW.js} +2 -2
  13. package/dist/chunk-UDMY6S4M.js +16 -0
  14. package/dist/chunk-UO6IYJA3.js +257 -0
  15. package/dist/chunk-WWBW6MPB.js +2 -0
  16. package/dist/cli.js +28 -27
  17. package/dist/index.d.ts +87 -48
  18. package/dist/index.js +1 -1
  19. package/dist/shader-browser-N5LY2NJX.js +1 -0
  20. package/dist/shader-capture-server.d.ts +13 -1
  21. package/dist/shader-capture-server.js +14 -14
  22. package/dist/{shader-config-AKZEKIRB.js → shader-config-TOBHWNCD.js} +1 -1
  23. package/dist/shader-workflow-JU5VYBN7.js +1 -0
  24. package/dist/status-CJTXLJBV.js +1 -0
  25. package/dist/transform.cjs +1 -1
  26. package/dist/transform.js +1 -1
  27. package/dist/webpack-loader.cjs +1 -1
  28. package/dist/webpack-loader.js +1 -1
  29. package/node/index.d.mts +2 -1
  30. package/node/index.mjs +10 -2
  31. package/node/layout.mjs +14 -2
  32. package/node/loader.mjs +5 -2
  33. package/node/worker.mjs +29 -6
  34. package/package.json +9 -4
  35. package/dist/browser-smoke-4MYMHKWB.js +0 -1
  36. package/dist/chunk-4SVF5BRM.js +0 -2
  37. package/dist/chunk-DCLDEPPB.js +0 -253
  38. package/dist/chunk-LMLJIVNY.cjs +0 -1
  39. package/dist/chunk-LSH64HEU.js +0 -80
  40. package/dist/chunk-NDIPQLTU.js +0 -16
  41. package/dist/chunk-NJITVI23.js +0 -2
  42. package/dist/chunk-O5FU2ASS.js +0 -16
  43. package/dist/chunk-QQKHDH26.js +0 -1
  44. package/dist/chunk-SBUKHO24.js +0 -1
  45. package/dist/shader-browser-6ICBHK3S.js +0 -1
  46. package/dist/shader-watch-JBUA4LP5.js +0 -1
  47. package/dist/shader-workflow-5EHHR32D.js +0 -1
  48. package/dist/status-GDVSLQWV.js +0 -1
@@ -1 +1 @@
1
- 'use strict';var chunkLMLJIVNY_cjs=require('./chunk-LMLJIVNY.cjs');Object.defineProperty(exports,"THREE_BLOCKS_WEBPACK_LOADER",{enumerable:true,get:function(){return chunkLMLJIVNY_cjs.b}});Object.defineProperty(exports,"createEsbuildShaderPlugin",{enumerable:true,get:function(){return chunkLMLJIVNY_cjs.g}});Object.defineProperty(exports,"createRollupShaderPlugin",{enumerable:true,get:function(){return chunkLMLJIVNY_cjs.h}});Object.defineProperty(exports,"resolveShaderAdapterThreeVersion",{enumerable:true,get:function(){return chunkLMLJIVNY_cjs.e}});Object.defineProperty(exports,"transformThreeWebGPUModule",{enumerable:true,get:function(){return chunkLMLJIVNY_cjs.f}});Object.defineProperty(exports,"withThreeBlocksNext",{enumerable:true,get:function(){return chunkLMLJIVNY_cjs.d}});Object.defineProperty(exports,"withThreeBlocksWebpack",{enumerable:true,get:function(){return chunkLMLJIVNY_cjs.c}});
1
+ 'use strict';var chunk7YWPJCDF_cjs=require('./chunk-7YWPJCDF.cjs');Object.defineProperty(exports,"THREE_BLOCKS_WEBPACK_LOADER",{enumerable:true,get:function(){return chunk7YWPJCDF_cjs.b}});Object.defineProperty(exports,"createEsbuildShaderPlugin",{enumerable:true,get:function(){return chunk7YWPJCDF_cjs.g}});Object.defineProperty(exports,"createRollupShaderPlugin",{enumerable:true,get:function(){return chunk7YWPJCDF_cjs.h}});Object.defineProperty(exports,"resolveShaderAdapterThreeVersion",{enumerable:true,get:function(){return chunk7YWPJCDF_cjs.e}});Object.defineProperty(exports,"transformThreeWebGPUModule",{enumerable:true,get:function(){return chunk7YWPJCDF_cjs.f}});Object.defineProperty(exports,"withThreeBlocksNext",{enumerable:true,get:function(){return chunk7YWPJCDF_cjs.d}});Object.defineProperty(exports,"withThreeBlocksWebpack",{enumerable:true,get:function(){return chunk7YWPJCDF_cjs.c}});
package/dist/transform.js CHANGED
@@ -1 +1 @@
1
- export{a as THREE_BLOCKS_WEBPACK_LOADER,f as createEsbuildShaderPlugin,g as createRollupShaderPlugin,d as resolveShaderAdapterThreeVersion,e as transformThreeWebGPUModule,c as withThreeBlocksNext,b as withThreeBlocksWebpack}from'./chunk-QQKHDH26.js';import'./chunk-4SVF5BRM.js';import'./chunk-NDIPQLTU.js';import'./chunk-TK566QET.js';import'./chunk-NJITVI23.js';import'./chunk-WNSGAV6N.js';import'./chunk-ECQE4D2U.js';import'./chunk-7X4DHW36.js';
1
+ export{a as THREE_BLOCKS_WEBPACK_LOADER,f as createEsbuildShaderPlugin,g as createRollupShaderPlugin,d as resolveShaderAdapterThreeVersion,e as transformThreeWebGPUModule,c as withThreeBlocksNext,b as withThreeBlocksWebpack}from'./chunk-RITS37ER.js';import'./chunk-WWBW6MPB.js';import'./chunk-UDMY6S4M.js';import'./chunk-TK566QET.js';import'./chunk-75JSWKB4.js';import'./chunk-WNSGAV6N.js';import'./chunk-ECQE4D2U.js';import'./chunk-7X4DHW36.js';
@@ -1 +1 @@
1
- 'use strict';var chunkLMLJIVNY_cjs=require('./chunk-LMLJIVNY.cjs');function o(e){return chunkLMLJIVNY_cjs.f(e,this.resourcePath,this.getOptions?.()??{})?.code??e}chunkLMLJIVNY_cjs.a(o,"threeBlocksShaderLoader");module.exports=o;
1
+ 'use strict';var chunk7YWPJCDF_cjs=require('./chunk-7YWPJCDF.cjs');function o(e){return chunk7YWPJCDF_cjs.f(e,this.resourcePath,this.getOptions?.()??{})?.code??e}chunk7YWPJCDF_cjs.a(o,"threeBlocksShaderLoader");module.exports=o;
@@ -1 +1 @@
1
- import {e}from'./chunk-QQKHDH26.js';import'./chunk-4SVF5BRM.js';import'./chunk-NDIPQLTU.js';import'./chunk-TK566QET.js';import'./chunk-NJITVI23.js';import'./chunk-WNSGAV6N.js';import'./chunk-ECQE4D2U.js';import {a}from'./chunk-7X4DHW36.js';function o(e$1){return e(e$1,this.resourcePath,this.getOptions?.()??{})?.code??e$1}a(o,"threeBlocksShaderLoader");export{o as default};
1
+ import {e}from'./chunk-RITS37ER.js';import'./chunk-WWBW6MPB.js';import'./chunk-UDMY6S4M.js';import'./chunk-TK566QET.js';import'./chunk-75JSWKB4.js';import'./chunk-WNSGAV6N.js';import'./chunk-ECQE4D2U.js';import {a}from'./chunk-7X4DHW36.js';function o(e$1){return e(e$1,this.resourcePath,this.getOptions?.()??{})?.code??e$1}a(o,"threeBlocksShaderLoader");export{o as default};
package/node/index.d.mts CHANGED
@@ -52,7 +52,8 @@ export interface RendererPage extends EventEmitter<{
52
52
  locator( selector: string ): RendererLocator;
53
53
  }
54
54
  export interface RendererContext {
55
- addInitScript<A>( script: string | { content: string } | ( ( arg: A ) => unknown ), arg?: A ): Promise<void>;
55
+ /** `workers: true` also runs the script in every worker thread, which browsers never do. */
56
+ addInitScript<A>( script: string | { content: string; workers?: boolean } | ( ( arg: A ) => unknown ), arg?: A ): Promise<void>;
56
57
  route( pattern: string, handler: ( route: Route ) => unknown ): Promise<void>;
57
58
  close(): Promise<void>;
58
59
  browser(): RendererBrowser;
package/node/index.mjs CHANGED
@@ -113,7 +113,7 @@ class NodePage extends EventEmitter {
113
113
 
114
114
  } );
115
115
  const result = await this.#call( 'goto', {
116
- url, viewport: this.#context.viewport, scripts: this.#context.scripts,
116
+ url, viewport: this.#context.viewport, scripts: this.#context.scripts, workerScripts: this.#context.workerScripts,
117
117
  routes: Boolean( this.#context.handler ), storage: this.#context.storage, media: this.#context.media,
118
118
  cookies: this.#context.cookies, gpu: this.#context.gpu,
119
119
  }, timeout );
@@ -336,6 +336,7 @@ class NodePage extends EventEmitter {
336
336
  class NodeContext {
337
337
 
338
338
  scripts = [];
339
+ workerScripts = [];
339
340
  pages = [];
340
341
  storage = {};
341
342
  cookies;
@@ -349,7 +350,14 @@ class NodeContext {
349
350
  }
350
351
  browser() { return this.owner; }
351
352
  async newPage() { const page = new NodePage( this ); this.pages.push( page ); return page; }
352
- async addInitScript( script, arg ) { this.scripts.push( typeof script === 'function' ? `(${script})(${JSON.stringify( arg )});` : typeof script === 'string' ? script : script.content ); }
353
+ async addInitScript( script, arg ) {
354
+
355
+ const source = typeof script === 'function' ? `(${script})(${JSON.stringify( arg )});` : typeof script === 'string' ? script : script.content;
356
+ this.scripts.push( source );
357
+ // `{ content, workers: true }` also runs in every worker thread (not a Playwright feature).
358
+ if ( script?.workers === true ) this.workerScripts.push( source );
359
+
360
+ }
353
361
  async route( pattern, handler ) {
354
362
 
355
363
  if ( this.pages.some( page => page.url() && ! page.isClosed() ) ) throw new Error( 'Configure native request routes before navigation.' );
package/node/layout.mjs CHANGED
@@ -3,6 +3,16 @@ import { createCanvas, GlobalFonts, ImageData, loadImage } from '@napi-rs/canvas
3
3
  import { transform } from 'lightningcss';
4
4
  import { parse as parseSelector, stringify as stringifySelector } from 'css-what';
5
5
 
6
+ // The user-agent defaults that change what text renders as. Without them an undeclared <h1>
7
+ // measures 400 / 16px here and 700 / 32px in every browser, so a capture records other text
8
+ // batch keys than a visitor demands. ponytail: `bolder` is a flat 700 (900 inside bold text is
9
+ // not modelled), and inline flow is not modelled at all; extend when a capture disagrees.
10
+ const bold = { 'font-weight': '700' }, italic = { 'font-style': 'italic' };
11
+ const userAgentStyle = {
12
+ H1: { ...bold, 'font-size': '2em' }, H2: { ...bold, 'font-size': '1.5em' }, H3: { ...bold, 'font-size': '1.17em' },
13
+ H4: bold, H5: { ...bold, 'font-size': '0.83em' }, H6: { ...bold, 'font-size': '0.67em' },
14
+ B: bold, STRONG: bold, TH: bold, I: italic, EM: italic, CITE: italic, VAR: italic, DFN: italic, ADDRESS: italic,
15
+ };
6
16
  const inherited = [ 'font-family', 'font-size', 'font-weight', 'font-style', 'line-height', 'letter-spacing', 'color', 'text-align', 'text-transform', 'visibility' ];
7
17
  const camel = name => name.replace( /-([a-z])/g, ( _, letter ) => letter.toUpperCase() );
8
18
  const kebab = name => name.replace( /[A-Z]/g, letter => `-${letter.toLowerCase()}` );
@@ -17,7 +27,8 @@ export async function installNativeLayout( dom ) {
17
27
  const { document } = dom;
18
28
  for ( const link of document.querySelectorAll( 'link[rel="stylesheet"]' ) ) {
19
29
 
20
- const response = await fetch( link.getAttribute( 'href' ) );
30
+ // Browsers name the destination; a Vite dev server answers anything else with the CSS's JS module.
31
+ const response = await fetch( link.getAttribute( 'href' ), { headers: { accept: 'text/css,*/*;q=0.1' } } );
21
32
  if ( ! response.ok ) throw new Error( `Stylesheet ${link.href}: HTTP ${response.status}` );
22
33
  const style = document.createElement( 'style' ); style.textContent = await response.text(); style.dataset.nativeURL = response.url;
23
34
  link.after( style );
@@ -165,7 +176,8 @@ export async function installNativeLayout( dom ) {
165
176
  const parentStyle = parent ? computed( parent ) : {};
166
177
  const result = { display: element.hidden || /^(STYLE|SCRIPT|LINK|HEAD|META)$/.test( element.tagName ) ? 'none' : 'block', 'font-size': '16px', 'font-weight': '400', 'font-family': 'sans-serif', 'line-height': 'normal', 'letter-spacing': '0px', color: 'rgb(0, 0, 0)', opacity: '1', 'text-align': 'left', 'text-transform': 'none', visibility: 'visible' };
167
178
  for ( const name of inherited ) if ( parentStyle[ name ] ) result[ name ] = parentStyle[ name ];
168
- Object.assign( result, registeredProperties );
179
+ // Unranked, so every author rule and inline style below still wins.
180
+ Object.assign( result, userAgentStyle[ element.tagName ], registeredProperties );
169
181
  for ( const [ name, value ] of Object.entries( parentStyle ) ) if ( name.startsWith( '--' ) ) result[ name ] = value;
170
182
  const ranks = {};
171
183
  const apply = ( declaration, priority, base = location.href, layer ) => {
package/node/loader.mjs CHANGED
@@ -7,6 +7,9 @@ let scopes;
7
7
  let network;
8
8
  let networkId = 0;
9
9
 
10
+ // Runtime guard shared by both fixes: r186 ships the same code at both sites.
11
+ const VERIFIED_REVISION = '[`185`,`186`].includes(globalThis.__THREE__)';
12
+
10
13
  // Version-gated platform fixes; leave upstream packages and shader recipes intact.
11
14
  export function patchNativeThreeCode( source ) {
12
15
 
@@ -15,7 +18,7 @@ export function patchNativeThreeCode( source ) {
15
18
 
16
19
  const assignment = /this\.gl\s*=\s*[\w$]+(?=\s*[,;)}])/g;
17
20
  if ( ! assignment.test( source ) ) throw new Error( 'Native Three.js CanvasTarget compatibility anchor changed.' );
18
- source = source.replace( assignment, value => `/*${canvasMarker}*/(${value},globalThis.__THREE__===\`185\`&&globalThis.__THREE_BLOCKS_NATIVE_CANVAS_TARGET__?.(this),this.gl)` );
21
+ source = source.replace( assignment, value => `/*${canvasMarker}*/(${value},${VERIFIED_REVISION}&&globalThis.__THREE_BLOCKS_NATIVE_CANVAS_TARGET__?.(this),this.gl)` );
19
22
 
20
23
  }
21
24
  // r185 destroys the device before its timestamp pool's pending map settles.
@@ -31,7 +34,7 @@ export function patchNativeThreeCode( source ) {
31
34
  const start = Math.max( 0, index - 450 );
32
35
  const match = call.exec( source.slice( start, index + label.length + 80 ) );
33
36
  if ( ! match ) throw new Error( 'Native Three.js timestamp-disposal compatibility anchor changed.' );
34
- edits.push( { index: start + match.index, length: match[ 0 ].length, replacement: `/*${marker}*/((globalThis.__THREE__ === \`185\` && this.isDisposed && ${match[ 2 ]}?.name === \`AbortError\`) ? void 0 : ${match[ 0 ]})` } );
37
+ edits.push( { index: start + match.index, length: match[ 0 ].length, replacement: `/*${marker}*/((${VERIFIED_REVISION} && this.isDisposed && ${match[ 2 ]}?.name === \`AbortError\`) ? void 0 : ${match[ 0 ]})` } );
35
38
 
36
39
  }
37
40
  for ( const edit of edits.reverse() ) source = source.slice( 0, edit.index ) + edit.replacement + source.slice( edit.index + edit.length );
package/node/worker.mjs CHANGED
@@ -23,6 +23,7 @@ let pageURL;
23
23
  let pageViewport;
24
24
  let cookieJar;
25
25
  let gpuEnabled = true;
26
+ let workerScripts = [];
26
27
  let paintPage;
27
28
  let importMap = {};
28
29
  let surfaceId = 0;
@@ -138,11 +139,11 @@ function run( source, filename = pageURL ) {
138
139
 
139
140
  }
140
141
 
141
- async function navigate( { url, viewport, scripts: initialScripts = [], routes: intercept, thread, imports = {}, source, blob, scopes = {}, storage = {}, media = [], cookies, gpu = true } ) {
142
+ async function navigate( { url, viewport, scripts: initialScripts = [], workerScripts: initialWorkerScripts = [], routes: intercept, thread, imports = {}, source, blob, scopes = {}, storage = {}, media = [], cookies, gpu = true } ) {
142
143
 
143
144
  pageURL = url; pageViewport = viewport; routes = intercept; importMap = imports;
144
145
  cookieJar = cookies ? CookieJar.deserializeSync( cookies ) : new CookieJar();
145
- gpuEnabled = gpu;
146
+ gpuEnabled = gpu; workerScripts = initialWorkerScripts;
146
147
  globalThis.Request = class Request extends OriginalRequest {
147
148
 
148
149
  constructor( input, init ) { super( input instanceof OriginalRequest ? input : new URL( input, pageURL ), init ); }
@@ -363,10 +364,21 @@ async function navigate( { url, viewport, scripts: initialScripts = [], routes:
363
364
  if ( copy.cancelBubble ) break;
364
365
 
365
366
  }
366
- const accepted = copy.cancelBubble ? ! copy.defaultPrevented : dispatchDOMEvent.call( this, copy );
367
+ let accepted = copy.cancelBubble ? ! copy.defaultPrevented : dispatchDOMEvent.call( this, copy );
368
+ // A browser's bubble path ends at window; LinkeDOM's ends at the document.
369
+ if ( copy.bubbles && ! copy.cancelBubble && path[ 0 ] === document && ! deliverToWindow( copy, this ) ) accepted = false;
367
370
  if ( ! accepted ) event.preventDefault();
368
371
  return accepted;
369
372
 
373
+ };
374
+ // The window target is Node's, which refuses a LinkeDOM event: the last hop carries a Node copy.
375
+ const deliverToWindow = ( event, target ) => {
376
+
377
+ const copy = new Event( event.type, { cancelable: event.cancelable } );
378
+ for ( const [ key, value ] of Object.entries( event ) ) if ( ! ( key in copy ) && ! key.startsWith( '_' ) ) copy[ key ] = value;
379
+ Object.defineProperty( copy, 'target', { value: target } );
380
+ return events.dispatchEvent( copy );
381
+
370
382
  };
371
383
  // LinkeDOM parses details as generic HTMLElements. Reflect its boolean state.
372
384
  Object.defineProperty( dom.HTMLDetailsElement, Symbol.hasInstance, { configurable: true, value: element => element?.localName === 'details' } );
@@ -668,6 +680,9 @@ async function navigate( { url, viewport, scripts: initialScripts = [], routes:
668
680
  }
669
681
 
670
682
  };
683
+ // Browsers never run page init scripts in workers. A capture host opts in, because a
684
+ // worker-owned renderer can only meet its capture runtime inside the worker realm.
685
+ for ( const script of workerScripts ) run( `(() => {\n${script}\n})();` );
671
686
  if ( thread === 'module' ) await import( url );
672
687
  else run( `(() => { const process = undefined;\n${source ?? modules[ url ] ?? await ( await fetchPage( url ) ).text()}\n})();` );
673
688
  return;
@@ -734,7 +749,7 @@ async function navigate( { url, viewport, scripts: initialScripts = [], routes:
734
749
 
735
750
  }
736
751
  document.readyState = 'interactive';
737
- document.dispatchEvent( new dom.Event( 'DOMContentLoaded' ) );
752
+ document.dispatchEvent( new dom.Event( 'DOMContentLoaded', { bubbles: true } ) );
738
753
  document.readyState = 'complete';
739
754
  globalThis.onload?.( new Event( 'load' ) );
740
755
  globalThis.dispatchEvent( new Event( 'load' ) );
@@ -1213,7 +1228,7 @@ class NativeWorker extends EventTarget {
1213
1228
  super();
1214
1229
  url = new URL( url, pageURL ).href;
1215
1230
  this.#thread = new Thread( new URL( './worker.mjs', import.meta.url ), {
1216
- execArgv: [ '--experimental-vm-modules' ], workerData: { url, viewport: pageViewport, thread: options.type ?? 'classic', imports: importMap, scopes: importScopes, routes, gpu: gpuEnabled, cookies: cookieJar.serializeSync(), blob: url.startsWith( 'blob:' ) ? resolveObjectURL( url ) : undefined },
1231
+ execArgv: [ '--experimental-vm-modules' ], workerData: { url, viewport: pageViewport, workerScripts, thread: options.type ?? 'classic', imports: importMap, scopes: importScopes, routes, gpu: gpuEnabled, cookies: cookieJar.serializeSync(), blob: url.startsWith( 'blob:' ) ? resolveObjectURL( url ) : undefined },
1217
1232
  } );
1218
1233
  this.#thread.on( 'message', message => {
1219
1234
 
@@ -1311,4 +1326,12 @@ if ( parentPort ) {
1311
1326
  ready = true;
1312
1327
  for ( const message of queued ) await receive( message );
1313
1328
 
1314
- } else process.on( 'message', message => command( jsonIPC ? decodeIPC( message ) : message ) );
1329
+ } else {
1330
+
1331
+ process.on( 'message', message => command( jsonIPC ? decodeIPC( message ) : message ) );
1332
+ // A page outlives nothing. When the process driving it dies (crash, kill, Ctrl-C) the IPC
1333
+ // channel closes; its render loop would otherwise keep this process and its GPU device
1334
+ // alive for hours, skewing every later measurement on the machine.
1335
+ process.on( 'disconnect', () => process.exit( 0 ) );
1336
+
1337
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@three-blocks/devtools",
3
- "version": "11.1.0",
3
+ "version": "12.0.0-alpha.399.g24d19fd0f1a1",
4
4
  "description": "Three Blocks devtools command engine for npx three-blocks; the runtime lives in three-blocks/devtools and the Vite plugin",
5
5
  "keywords": [
6
6
  "three",
@@ -101,9 +101,10 @@
101
101
  "devDependencies": {
102
102
  "@gltf-transform/functions": "4.4.2",
103
103
  "@types/node": "^22.10.0",
104
- "@types/three": "0.185.0",
104
+ "@types/three": "0.186.0",
105
105
  "create-vite": "9.1.1",
106
- "three-blocks": "0.12.1",
106
+ "three-blocks": "0.13.0-alpha.399.g24d19fd0f1a1",
107
+ "three-r185": "npm:three@0.185.1",
107
108
  "tsup": "^8.0.0",
108
109
  "vite": "^7.2.2",
109
110
  "vitest": "^4.1.8"
@@ -113,12 +114,16 @@
113
114
  },
114
115
  "peerDependencies": {
115
116
  "three": ">=0.185.0",
116
- "three-blocks": ">=0.12.1 <0.13.0",
117
+ "three-blocks": "0.13.0-alpha.399.g24d19fd0f1a1",
117
118
  "vite": ">=7.2.2 <9.0.0"
118
119
  },
119
120
  "peerDependenciesMeta": {
120
121
  "vite": {
121
122
  "optional": true
122
123
  }
124
+ },
125
+ "threeBlocks": {
126
+ "channel": "alpha",
127
+ "site": "https://preprod.threejs-blocks.com"
123
128
  }
124
129
  }
@@ -1 +0,0 @@
1
- export{d as BROWSER_SMOKE_OPTIMIZE_DEPENDENCIES,e as classifyRecoveredTextErrors,i as formatBrowserPreviewReport,g as formatBrowserSmokeReport,a as parseBrowserSmokeLifecycle,c as readAfterInitialReadiness,h as runBrowserPreview,f as runBrowserSmoke,b as screenshotLuminance}from'./chunk-DCLDEPPB.js';import'./chunk-BBODS5RH.js';import'./chunk-O5FU2ASS.js';import'./chunk-CMMYXGQ3.js';import'./chunk-MIJXPQPM.js';import'./chunk-LSH64HEU.js';import'./chunk-ZG3LO3VB.js';import'./chunk-4SVF5BRM.js';import'./chunk-NDIPQLTU.js';import'./chunk-TK566QET.js';import'./chunk-NJITVI23.js';import'./chunk-WNSGAV6N.js';import'./chunk-ECQE4D2U.js';import'./chunk-7X4DHW36.js';
@@ -1,2 +0,0 @@
1
- import {b as b$1}from'./chunk-NDIPQLTU.js';import {j as j$1,a as a$1}from'./chunk-ECQE4D2U.js';import {a}from'./chunk-7X4DHW36.js';import {createRequire}from'module';import c from'path';import {THREE_WEBGPU_R185_COMPATIBILITY}from'three-blocks/shaders';import {transformThreeWebgpuProviderHooks,transformThreeWebgpuCaptureInstrumentation}from'three-blocks/vite';var s;async function d(){s===void 0&&(s=(async()=>{let e=createRequire(c.join(process.cwd(),"package.json")).resolve("@three-blocks/devtools/browser/shader-capture"),t=c.resolve(c.dirname(e),"../..");return (await j$1(t,e,a$1.metadata,"Shader capture browser runtime")).data.toString("utf8")})());let r=s;try{return await r}catch(e){throw s===r&&(s=void 0),e}}a(d,"loadShaderCaptureRuntimeSource");var b="virtual:three-blocks-shader-capture-client",S="\0three-blocks:shader-capture-client",l="virtual:three-blocks-shader-capture-runtime",T="\0three-blocks:shader-capture-runtime";async function j(){let r=await d(),e=r.replace(/\bexport\{[^{}]*\};?\s*$/u,"");if(e===r)throw new Error("Shader capture browser runtime no longer has the expected final ESM export list.");return e}a(j,"loadShaderCaptureRuntimeScriptSource");function I(r){let e=r.split("?",1)[0];return e===void 0?false:e.split(c.sep).join("/").endsWith("/build/three.webgpu.js")}a(I,"isThreeWebGPUModule");function y(r){let e=/^(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/u.exec(r);return e?.[1]==="0"&&e[2]==="185"}a(y,"supportedVersion");function w(r,e,t={}){if(!y(e))throw new Error(`Shader provider transform ${THREE_WEBGPU_R185_COMPATIBILITY} supports Three.js 0.185.x; received "${e}".`);let u=transformThreeWebgpuProviderHooks(r,{threeVersion:e,...t.threeRevision===void 0?{}:{threeRevision:t.threeRevision},id:"three/build/three.webgpu.js"}),a=u.state==="already-applied",i=u.code;return t.instrumentCapture&&(i=transformThreeWebgpuCaptureInstrumentation(i,{...t.captureRuntimeImport===void 0?{}:{runtimeImport:t.captureRuntimeImport},...t.forceWebGL===true?{forceWebGL:true}:{}}).code),{code:i,alreadyPresent:a,captureApplied:t.instrumentCapture===true}}a(w,"applyShaderProviderTransform");var A=/this\.trackTimestamp\s*=\s*\(\s*parameters\.trackTimestamp\s*===\s*true\s*\);/gu,_="Object.defineProperty( this, 'trackTimestamp', { get: () => false, set: () => {} } );";function $(r,e={}){if(!y(r))throw new Error(`Shader provider transform ${THREE_WEBGPU_R185_COMPATIBILITY} supports Three.js 0.185.x; received "${r}".`);let t={seen:false,applied:false,alreadyPresent:false};return {plugin:{name:"three-blocks:shader-provider-transform",enforce:"pre",config(){return {optimizeDeps:{exclude:["three","three/webgpu","three/tsl"]},resolve:{dedupe:["three"]}}},resolveId(a){return e.capture&&a===b?S:e.capture&&a===l?T:null},async load(a){return e.capture?a===T?d():a===S?[`export * from '${l}';`,`import { configureThreeBlocksShaderCapture } from '${l}';`,`configureThreeBlocksShaderCapture( ${JSON.stringify({capture:e.capture.capture,backend:e.capture.forceWebGL===true?"webgl":"webgpu",forceLive:e.capture.forceLive,driven:e.capture.driven,settleFrames:e.capture.settleFrames,settleTimeoutMs:e.capture.settleTimeoutMs,visibilityGuard:e.capture.visibilityGuard,captureId:e.capture.captureId,sessionKey:e.capture.sessionKey,token:e.capture.token,readiness:e.capture.readiness??{},transform:b$1})} );`].join(`
2
- `):null:null},transform(a,i){if(!I(i))return null;t.seen=true,t.id=i;try{let n=w(a,r,{instrumentCapture:e.capture!==void 0,forceWebGL:e.capture?.forceWebGL===!0,...e.capture!==void 0?{captureRuntimeImport:b}:{}}),p=e.disableTimestampQueries===!0?n.code.replace(A,_):n.code;if(e.disableTimestampQueries===!0&&p===n.code)throw new Error("Three.js timestamp tracking anchor drifted; refusing software WebGPU capture.");return t.applied=!0,t.alreadyPresent=n.alreadyPresent,t.captureApplied=n.captureApplied,p===a?null:{code:p,map:null}}catch(n){throw t.error=n instanceof Error?n.message:String(n),n}}},status:t}}a($,"createShaderProviderTransform");function U(r){if(r.error)throw new Error(r.error);if(!r.seen||!r.applied)throw new Error(`The version-gated shader provider transform was not applied (${r.seen?"module seen":"three/webgpu not seen"}).`)}a(U,"assertShaderProviderTransform");export{d as a,b,j as c,I as d,w as e,$ as f,U as g};
@@ -1,253 +0,0 @@
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 +0,0 @@
1
- 'use strict';var fs=require('fs'),module$1=require('module'),d=require('path'),shaders=require('three-blocks/shaders'),vite=require('three-blocks/vite');require('fs/promises'),require('crypto');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var d__default=/*#__PURE__*/_interopDefault(d);var x=Object.defineProperty;var i=(e,r)=>x(e,"name",{value:r,configurable:true});function y(e){let r=e.split("?",1)[0];return r===void 0?false:r.split(d__default.default.sep).join("/").endsWith("/build/three.webgpu.js")}i(y,"isThreeWebGPUModule");function O(e){let r=/^(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/u.exec(e);return r?.[1]==="0"&&r[2]==="185"}i(O,"supportedVersion");function h(e,r,t={}){if(!O(r))throw new Error(`Shader provider transform ${shaders.THREE_WEBGPU_R185_COMPATIBILITY} supports Three.js 0.185.x; received "${r}".`);let n=vite.transformThreeWebgpuProviderHooks(e,{threeVersion:r,...t.threeRevision===void 0?{}:{threeRevision:t.threeRevision},id:"three/build/three.webgpu.js"}),a=n.state==="already-applied",o=n.code;return t.instrumentCapture&&(o=vite.transformThreeWebgpuCaptureInstrumentation(o,{...t.captureRuntimeImport===void 0?{}:{runtimeImport:t.captureRuntimeImport},...t.forceWebGL===true?{forceWebGL:true}:{}}).code),{code:o,alreadyPresent:a,captureApplied:t.instrumentCapture===true}}i(h,"applyShaderProviderTransform");var g="@three-blocks/devtools/webpack-loader";function S(e){if(typeof e=="string")return e===g;if(Array.isArray(e))return e.some(S);if(e===null||typeof e!="object")return false;let r=e;return r.loader===g||S(r.use)}i(S,"webpackRuleUsesShaderLoader");function k(e){let r=b(process.cwd()),t=i(a=>T(r,a),"exact"),n={...e.resolve?.alias,...t("three")===void 0?{}:{three$:t("three")},...t("three/webgpu")===void 0?{}:{"three/webgpu$":t("three/webgpu")},...t("three/tsl")===void 0?{}:{"three/tsl$":t("three/tsl")},"three/addons":d__default.default.join(r.root,"examples/jsm"),"three/examples/jsm":d__default.default.join(r.root,"examples/jsm")};return {...e,resolve:{...e.resolve,alias:n}}}i(k,"withTargetThreeAliases");function E(e){let r=k(e),t=r.module?.rules??[];return t.some(S)?r:{...r,module:{...r.module,rules:[...t,{enforce:"pre",test:/three[\\/]build[\\/]three\.webgpu\.js$/u,use:[{loader:g}]}]}}}i(E,"withShaderWebpackRule");function Er(e){return E(e)}i(Er,"withThreeBlocksWebpack");function Rr(e){let t=e.webpack;return {...e,webpack(n,...a){let o=t?.call(this,n,...a)??n,s=a[0];return s!==null&&typeof s=="object"&&Reflect.get(s,"isServer")===true?k(o):E(o)}}}i(Rr,"withThreeBlocksNext");function b(e){let r;try{r=module$1.createRequire(d__default.default.join(d__default.default.resolve(e),"package.json")).resolve("three");}catch(o){throw new Error("The shader adapter could not resolve Three.js from the target project.",{cause:o})}let t=d__default.default.dirname(r),n,a;for(;;){let o=d__default.default.join(t,"package.json");if(fs.existsSync(o)){let c=JSON.parse(fs.readFileSync(o,"utf8"));if(c.name==="three"){n=o,a=c;break}}let s=d__default.default.dirname(t);if(s===t)break;t=s;}if(n===void 0)throw new Error(`The shader adapter could not locate Three.js package metadata from ${r}.`);if(typeof a?.version!="string"||a.version.length===0)throw new Error(`The resolved Three.js package has no version: ${n}`);return {root:d__default.default.dirname(n),version:a.version,exports:a.exports}}i(b,"resolveThreePackage");function F(e=process.cwd()){return b(e).version}i(F,"resolveShaderAdapterThreeVersion");function R(e){return {version:e.threeVersion??F(e.root),capture:e.capture??process.env.THREE_BLOCKS_SHADER_TOOL==="1"}}i(R,"resolvedOptions");function Tr(e,r,t={}){if(!y(r))return null;let n=R(t);return h(e,n.version,{instrumentCapture:n.capture})}i(Tr,"transformThreeWebGPUModule");function m(e){if(typeof e=="string")return e;if(Array.isArray(e)){for(let t of e){let n=m(t);if(n!==void 0)return n}return}if(e===null||typeof e!="object")return;let r=e;for(let t of ["browser","import","default"]){let n=m(r[t]);if(n!==void 0)return n}}i(m,"exportTarget");function T(e,r){if(e.exports===null||typeof e.exports!="object")return;let t=e.exports,n=r==="three"?".":`./${r.slice(6)}`,a=m(t[n]);if(a!==void 0)return d__default.default.resolve(e.root,a);for(let[o,s]of Object.entries(t)){let c=o.indexOf("*");if(c<0)continue;let u=o.slice(0,c),l=o.slice(c+1);if(!n.startsWith(u)||!n.endsWith(l))continue;let p=n.slice(u.length,n.length-l.length),f=m(s);if(f!==void 0)return d__default.default.resolve(e.root,f.replaceAll("*",p))}}i(T,"resolveThreeExport");function xr(e={}){let r=e.root??process.cwd(),t=b(r),n={version:e.threeVersion??t.version,capture:e.capture??process.env.THREE_BLOCKS_SHADER_TOOL==="1"};return {name:"three-blocks-shader-provider",setup(a){a.onResolve?.({filter:/^three(?:\/.*)?$/},o=>{let s=T(t,o.path);return s===void 0?void 0:{path:s}}),a.onLoad({filter:/three[\\/]build[\\/]three\.webgpu\.js$/},async o=>{let s=await new Promise((u,l)=>{fs.readFile(o.path,"utf8",(p,f)=>{p?l(p):u(f);});});return {contents:h(s,n.version,{instrumentCapture:n.capture}).code,loader:"js"}});}}}i(xr,"createEsbuildShaderPlugin");function Pr(e={}){let r=R(e);return {name:"three-blocks-shader-provider",enforce:"pre",transform(t,n){return y(n)?{code:h(t,r.version,{instrumentCapture:r.capture}).code,map:null}:null}}}i(Pr,"createRollupShaderPlugin");exports.a=i;exports.b=g;exports.c=Er;exports.d=Rr;exports.e=F;exports.f=Tr;exports.g=xr;exports.h=Pr;