@three-blocks/devtools 2.0.0-alpha.238.g8723f0a28ca3 → 3.0.0-alpha.282.g3f938d990c02
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +63 -37
- package/dist/{browser-smoke-EIKJ6OVK.js → browser-smoke-JHZLPGEB.js} +1 -1
- package/dist/{chunk-GA7PGW2R.js → chunk-3CKEE22B.js} +1 -1
- package/dist/{chunk-OQLHTDDH.js → chunk-AIAYEDXX.js} +1 -1
- package/dist/{chunk-4YRR36JN.js → chunk-FKZT7XLM.js} +18 -18
- package/dist/{chunk-TUIINI6U.js → chunk-L2CZ7RSV.js} +1 -1
- package/dist/{chunk-LUULHXFK.js → chunk-NQIAU3XU.js} +6 -6
- package/dist/chunk-QJFPNM6W.js +2 -0
- package/dist/chunk-YHHGR2AJ.js +80 -0
- package/dist/cli.js +8 -8
- package/dist/{environment-bake-XMRKQJXM.js → environment-bake-BGMGFAVK.js} +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +5 -5
- package/dist/{shader-browser-EYE3UT2U.js → shader-browser-523TEBVA.js} +1 -1
- package/dist/{shader-browser-WF4HNSAV.js → shader-browser-YPBP3WQY.js} +1 -1
- package/dist/shader-capture-server.d.ts +1 -1
- package/dist/shader-capture-server.js +5 -5
- package/dist/{shader-watch-ISNWIAXN.js → shader-watch-XY6A2KGQ.js} +1 -1
- package/dist/shader-workflow-T7W7UHWJ.js +2 -0
- package/dist/{status-D2RF6QTL.js → status-RFA7WAM6.js} +1 -1
- package/dist/transform.js +1 -1
- package/dist/webpack-loader.js +1 -1
- package/package.json +4 -4
- package/dist/chunk-V34C7NIM.js +0 -80
- package/dist/chunk-W6UL2OW7.js +0 -2
- package/dist/shader-workflow-T72N2CLS.js +0 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {realpath,readFile,mkdir,readdir,unlink,lstat,open,rename,rm}from'fs/promises';import b from'path';import {parsePrecompiledManifest,SHADER_HYDRATION_SCHEMA_VERSION,SHADER_RECIPE_SCHEMA_VERSION,SHADER_ADDRESS_SCHEMA_VERSION,PRECOMPILED_MANIFEST_VERSION,THREE_WEBGL_R185_COMPATIBILITY,THREE_WEBGPU_R185_COMPATIBILITY,THREE_R186DEV_VERSION,THREE_WEBGPU_R186DEV_COMPATIBILITY}from'three-blocks/shaders';import {createHash,randomUUID}from'crypto';import {createRequire}from'module';var kt=Object.defineProperty;var o=(e,t)=>kt(e,"name",{value:t,configurable:true});var $=Object.freeze({metadata:1024*1024,receipt:2*1024*1024,manifest:32*1024*1024,semanticInput:8*1024*1024,semanticTotal:64*1024*1024,metrics:8*1024*1024,texture:128*1024*1024,packageJson:1024*1024});function De(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"?e.code:void 0}o(De,"errorCode");function I(e){return createHash("sha256").update(e).digest("hex")}o(I,"sha256");async function C(e){try{return await lstat(e),!0}catch(t){if(De(t)==="ENOENT")return false;throw t}}o(C,"pathExists");function v(e,t){let r=b.relative(e,t);return r===""||!b.isAbsolute(r)&&r!==".."&&!r.startsWith(`..${b.sep}`)}o(v,"isWithin");function z(e){return JSON.stringify(e)}o(z,"displayPath");async function Fe(e,t,r){let n=await open(e,"r");try{let[i,s,a]=await Promise.all([lstat(e),n.stat(),realpath(e)]);if(i.isSymbolicLink())throw new Error(`${r} must not be a symbolic link: ${z(e)}.`);if(!s.isFile())throw new Error(`${r} must be a regular file: ${z(e)}.`);if(s.size>t)throw new Error(`${r} exceeds the ${t}-byte inspection limit: ${z(e)}.`);let c=await n.readFile();if(c.byteLength>t)throw new Error(`${r} grew beyond the ${t}-byte inspection limit while being read.`);return {path:a,data:c}}finally{await n.close();}}o(Fe,"readBoundedRegularFile");async function ce(e,t){let r=b.dirname(e);await mkdir(r,{recursive:true});try{if((await lstat(e)).isSymbolicLink())throw new Error(`Atomic write target must not be a symbolic link: ${z(e)}.`)}catch(s){if(De(s)!=="ENOENT")throw s}let n=b.join(r,`.${b.basename(e)}.${process.pid}.${randomUUID()}.tmp`),i;try{i=await open(n,"wx",384),await i.writeFile(t),await i.sync(),await i.close(),i=void 0,await rename(n,e);}finally{await i?.close().catch(()=>{}),await rm(n,{force:true});}}o(ce,"writeAtomicRegularFile");async function ye(e,t,r){return Fe(e,t,r)}o(ye,"readExternalRegularFile");async function U(e,t,r){let n=b.resolve(e),i=b.resolve(t);if(!v(n,i))throw new Error(`${r} escapes its allowed directory.`);let s=await lstat(i);if(s.isSymbolicLink())throw new Error(`${r} must not be a symbolic link.`);if(!s.isDirectory())throw new Error(`${r} must be a directory.`);let[a,c]=await Promise.all([realpath(n),realpath(i)]);if(!v(a,c))throw new Error(`${r} resolves outside its allowed directory.`);return c}o(U,"canonicalDirectoryWithin");async function _(e,t,r,n){let i=b.resolve(e),s=b.resolve(t);if(!v(i,s)||i===s)throw new Error(`${n} escapes its allowed directory.`);let a=await Fe(s,r,n),c=await realpath(i);if(!v(c,a.path)||c===a.path)throw new Error(`${n} resolves outside its allowed directory.`);return a}o(_,"readRegularFileWithin");async function Ve(e,t,r,n=8192){let s=[await U(e,t,"Inspected directory")],a=[],c=0;for(;s.length>0;){let f=s.shift();if(f===void 0)break;let m=(await readdir(f,{withFileTypes:true})).sort((h,d)=>h.name.localeCompare(d.name));for(let h of m){if(c+=1,c>n)throw new Error(`Inspected directory exceeds the ${n}-entry limit.`);let d=b.join(f,h.name);if(h.isSymbolicLink())throw new Error(`Inspected directory contains a symbolic link: ${z(b.relative(e,d))}.`);if(h.isDirectory()){s.push(await U(e,d,"Nested inspected directory"));continue}if(h.isFile()&&r(h.name))a.push(d);else if(r(h.name))throw new Error(`Semantic input is not a regular file: ${z(d)}.`)}}return a.sort()}o(Ve,"listRegularFilesRecursively");var ue=/^[a-f0-9]{64}$/,Mt=/^[0-9A-Za-z][0-9A-Za-z.+_-]{0,127}$/,He=/^[a-z0-9][a-z0-9_-]{0,63}$/,ve=/^[0-9A-Za-z][0-9A-Za-z._/-]{0,127}$/;function l(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}o(l,"isRecord");function W(e){return typeof e=="string"&&Mt.test(e)}o(W,"isSafeVersion");function Se(e){if(e.length===0||e.length>512||e.includes("\\")||/[\u0000-\u001f\u007f]/.test(e))return false;let t=e.split("/");return !e.startsWith("/")&&t.every(r=>r.length>0&&r!=="."&&r!=="..")}o(Se,"isSafeRelativePath");function ze(e){if(!l(e)||e.schemaVersion!==2)throw new Error("three-blocks.json must use schemaVersion 2.");if(typeof e.template!="string"||!He.test(e.template))throw new Error("three-blocks.json has an invalid default shader scene key.");if(!Array.isArray(e.layers)||!e.layers.every(t=>typeof t=="string"&&ve.test(t))||new Set(e.layers).size!==e.layers.length)throw new Error("three-blocks.json has invalid layers.");if(e.generator!==void 0&&(!l(e.generator)||typeof e.generator.name!="string"||!ve.test(e.generator.name)||!W(e.generator.version)))throw new Error("three-blocks.json has invalid generator metadata.");if(!l(e.runtime)||!W(e.runtime.three)||!W(e.runtime.threeBlocks))throw new Error("three-blocks.json has invalid runtime versions.");if(!l(e.features)||typeof e.features.text!="boolean")throw new Error("three-blocks.json has invalid feature metadata.");if(!l(e.protocol)||e.protocol.resultFile!==1)throw new Error("three-blocks.json has an unsupported protocol schema.");if(e.artifacts!==void 0){if(!l(e.artifacts)||typeof e.artifacts.shaders!="string"||!["fresh","pending"].includes(e.artifacts.shaders)||typeof e.artifacts.text!="string"||!["fresh","pending","not-applicable"].includes(e.artifacts.text))throw new Error("three-blocks.json has invalid artifact metadata.");if(e.features.text?e.artifacts.text==="not-applicable":e.artifacts.text!=="not-applicable")throw new Error("three-blocks.json text artifact state does not match the text capability.")}return {schemaVersion:2,template:e.template,layers:e.layers,...e.generator===void 0?{}:{generator:{name:e.generator.name,version:e.generator.version}},runtime:{three:e.runtime.three,threeBlocks:e.runtime.threeBlocks},features:{text:e.features.text},...e.artifacts===void 0?{}:{artifacts:{shaders:e.artifacts.shaders,text:e.artifacts.text}},protocol:{resultFile:1}}}o(ze,"parseProjectMetadata");function Ct(e){if(!l(e))throw new Error("Shader coverage is missing.");for(let t of ["render","vertex","fragment","compute"])if(typeof e[t]!="number"||!Number.isSafeInteger(e[t])||e[t]<0)throw new Error(`Shader coverage.${t} must be a non-negative integer.`);return e}o(Ct,"parseCoverage");function It(e,t){if(!l(e))throw new Error(`Shader receipt inputs for "${t}" are invalid.`);let r=Object.entries(e);if(r.length===0||r.length>4096)throw new Error(`Shader receipt inputs for "${t}" must contain between 1 and 4096 files.`);for(let[n,i]of r)if(!Se(n)||typeof i!="string"||!ue.test(i))throw new Error(`Shader receipt input for "${t}" is invalid.`)}o(It,"parseInputs");function le(e){if(!l(e)||e.schemaVersion!==2||!l(e.runtime)||!W(e.runtime.three)||!W(e.runtime.threeBlocks)||typeof e.runtime.threeBlocksShaderClosure!="string"||!ue.test(e.runtime.threeBlocksShaderClosure)||!l(e.scenes))throw new Error("Shader meta.json does not match receipt schema 2.");if(e.runtime.capture!==void 0&&(!l(e.runtime.capture)||typeof e.runtime.capture.userAgent!="string"||e.runtime.capture.userAgent.length>1024||typeof e.runtime.capture.adapter!="string"||e.runtime.capture.adapter.length>1024||!Array.isArray(e.runtime.capture.features)||e.runtime.capture.features.length>256||!e.runtime.capture.features.every(r=>typeof r=="string"&&r.length>0&&r.length<=128)))throw new Error("Shader meta.json has invalid browser capture provenance.");let t=Object.entries(e.scenes);if(t.length===0)throw new Error("Shader meta.json contains no scenes.");for(let[r,n]of t){let i=r.endsWith(".webgl")?"webgl":"webgpu",s=i==="webgl"?r.slice(0,-6):r;if(!He.test(s)||!l(n)||n.backend!==void 0&&n.backend!==i||typeof n.artifact!="string"||!Se(n.artifact)||!n.artifact.endsWith(`.${i}.ts`)||typeof n.artifactHash!="string"||!ue.test(n.artifactHash))throw new Error(`Shader receipt for "${r}" is invalid.`);if(n.asset===void 0!=(n.assetHash===void 0)||n.asset!==void 0&&(typeof n.asset!="string"||!Se(n.asset)||!n.asset.endsWith(".json")||typeof n.assetHash!="string"||!ue.test(n.assetHash)))throw new Error(`Shader static asset receipt for "${r}" is invalid.`);if(It(n.inputs,r),Ct(n.coverage),n.bytes!==void 0&&(!Number.isSafeInteger(n.bytes)||Number(n.bytes)<0))throw new Error(`Shader receipt byte count for "${r}" is invalid.`);if(n.skipped!==void 0&&(!l(n.skipped)||!Number.isSafeInteger(n.skipped.render)||Number(n.skipped.render)<0||!Number.isSafeInteger(n.skipped.compute)||Number(n.skipped.compute)<0))throw new Error(`Shader receipt skipped-build counts for "${r}" are invalid.`)}if(e.tool!==void 0&&(!l(e.tool)||e.tool.name!=="@three-blocks/devtools"||!W(e.tool.version)||typeof e.tool.compatibility!="string"||!Number.isSafeInteger(e.tool.transform)||!Number.isSafeInteger(e.tool.address)||!Number.isSafeInteger(e.tool.recipe)||!Number.isSafeInteger(e.tool.hydration)))throw new Error("Shader meta.json has invalid tool compatibility metadata.");if(l(e.tool)&&e.tool.compatibilities!==void 0&&(!l(e.tool.compatibilities)||Object.entries(e.tool.compatibilities).some(([r,n])=>r!=="webgpu"&&r!=="webgl"||typeof n!="string"||n.length===0)))throw new Error("Shader meta.json has invalid backend compatibility metadata.");return e}o(le,"parseShaderReceipt");var Je="three-blocks.shaders.json",Ee=".three-blocks/shaders";var _t=/^[a-z0-9][a-z0-9_-]{0,63}$/u,Pt=/^[A-Za-z_$][A-Za-z0-9_$]*(?:\.[A-Za-z_$][A-Za-z0-9_$]*)*$/u,Ue=64,We=64,Ot={schemaVersion:1,backend:"both",scenes:[{key:"default",url:"/"}]};function qe(e="both"){return e==="both"?["webgpu","webgl"]:[e]}o(qe,"shaderBackends");function J(e,t){return e.backend===void 0?t:t.filter(r=>r===e.backend)}o(J,"shaderSceneBackends");function K(e,t){return t==="webgpu"?e:`${e}.webgl`}o(K,"shaderReceiptKey");function Ge(e,t,r){if(e===void 0)return r;if(typeof e!="string"||e.length===0||e.length>512||b.isAbsolute(e)||/[\u0000-\u001f\u007f]/u.test(e))throw new Error(`${t} must be a bounded project-relative directory.`);let n=b.posix.normalize(e.replaceAll("\\","/")).replace(/\/+$/u,"");if(n==="."||n===".."||n.startsWith("../"))throw new Error(`${t} must stay inside the project.`);return n}o(Ge,"safeProjectDirectory");function Nt(e,t){let r=Ge(e,t,"");if(typeof e!="string"||e.endsWith("/"))throw new Error(`${t} must be a project-relative file.`);return r}o(Nt,"safeProjectFile");function L(e,t,r,n,i){if(e===void 0)return i;if(!Number.isSafeInteger(e)||Number(e)<r||Number(e)>n)throw new Error(`${t} must be an integer in ${r}...${n}.`);return Number(e)}o(L,"boundedInteger");function Ke(e,t,r){if(e===void 0)return r;if(typeof e!="number"||!Number.isFinite(e)||e<0||e>1)throw new Error(`${t} must be a finite ratio in 0...1.`);return e}o(Ke,"finiteRatio");function Ye(e,t){if(typeof e!="string"||e.length===0||e.length>2048||/[\u0000-\u001f\u007f]/u.test(e))throw new Error(`${t} must be a bounded project-relative URL.`);let r;try{r=new URL(e,"http://three-blocks.invalid/");}catch{throw new Error(`${t} is not a valid URL.`)}if(r.origin!=="http://three-blocks.invalid"||r.hash.length>0)throw new Error(`${t} must stay within the project and must not contain a fragment.`);return `${r.pathname}${r.search}`}o(Ye,"safeBrowserUrl");function Lt(e){if(!Array.isArray(e)||e.length===0||e.length>Ue)throw new Error(`Shader config scenes must contain 1...${Ue} entries.`);let t=new Set;return e.map((r,n)=>{if(!l(r)||typeof r.key!="string"||!_t.test(r.key))throw new Error(`Shader config scene ${n} has an invalid key.`);if(t.has(r.key))throw new Error(`Shader config scene key "${r.key}" is duplicated.`);t.add(r.key);let i=r.parityFrames,s=r.maxDiffRatio;if(r.inputs!==void 0&&(!Array.isArray(r.inputs)||r.inputs.length===0||r.inputs.length>We))throw new Error(`Shader config scene "${r.key}" inputs must contain 1...${We} files.`);let a=r.inputs===void 0?void 0:r.inputs.map((c,f)=>Nt(c,`Shader config scene "${r.key}" input ${f}`));if(a!==void 0&&new Set(a).size!==a.length)throw new Error(`Shader config scene "${r.key}" inputs must be unique.`);if(r.runtimeMotion!==void 0&&typeof r.runtimeMotion!="boolean")throw new Error(`Shader config scene "${r.key}" runtimeMotion must be a boolean.`);if(r.backend!==void 0&&r.backend!=="webgpu"&&r.backend!=="webgl")throw new Error(`Shader config scene "${r.key}" backend must be "webgpu" or "webgl".`);return {key:r.key,url:Ye(r.url,`Shader config scene "${r.key}" URL`),...r.backend===void 0?{}:{backend:r.backend},requiresText:r.requiresText===true,...a===void 0?{}:{inputs:a},...i===void 0?{}:{parityFrames:L(i,`Shader config scene "${r.key}" parityFrames`,0,1e4,0)},...s===void 0?{}:{maxDiffRatio:Ke(s,`Shader config scene "${r.key}" maxDiffRatio`,.01)},...r.runtimeMotion===true?{runtimeMotion:true}:{}}})}o(Lt,"parseScenes");function we(e){if(!l(e)||e.schemaVersion!==void 0&&e.schemaVersion!==1)throw new Error("Shader config must use schemaVersion 1.");let t=e.viewport;if(t!==void 0&&!l(t))throw new Error("Shader config viewport must be an object.");let r=e.parity;if(r!==void 0&&!l(r))throw new Error("Shader config parity must be an object.");let n=e.bridge;if(n!==void 0&&!l(n))throw new Error("Shader config bridge must be an object.");let i=l(n)?n.deterministicModule:void 0;i!==void 0&&Ye(i,"Shader deterministic module");let s=e.readiness;if(s!==void 0&&!l(s))throw new Error("Shader config readiness must be an object.");let a=l(s)?s.selector:void 0;if(a!==void 0&&(typeof a!="string"||a.length===0||a.length>512||/[\u0000-\u001f\u007f]/u.test(a)))throw new Error("Shader readiness selector must be a bounded, non-empty CSS selector.");let c=l(s)?s.global:void 0;if(c!==void 0&&(typeof c!="string"||!Pt.test(c)))throw new Error("Shader readiness global must be a dot-separated JavaScript property path.");if(e.backend!==void 0&&e.backend!=="webgpu"&&e.backend!=="webgl"&&e.backend!=="both")throw new Error('Shader config backend must be "webgpu", "webgl", or "both".');let f=L(e.timeoutMs,"Shader timeoutMs",1e3,15*6e4,24e4);return {schemaVersion:1,backend:e.backend??"both",scenes:Lt(e.scenes),settleFrames:L(e.settleFrames,"Shader settleFrames",0,1e4,60),settleTimeoutMs:L(e.settleTimeoutMs,"Shader settleTimeoutMs",1e3,15*6e4,3e4),browserRelaunchScenes:L(e.browserRelaunchScenes,"Shader browserRelaunchScenes",1,64,8),timeoutMs:f,maxTimeoutMs:Math.max(f,L(e.maxTimeoutMs,"Shader maxTimeoutMs",1e3,15*6e4,f)),viewport:{width:L(l(t)?t.width:void 0,"Shader viewport width",64,8192,1024),height:L(l(t)?t.height:void 0,"Shader viewport height",64,8192,640)},parity:{frames:L(l(r)?r.frames:void 0,"Shader parity frames",0,1e4,90),channelTolerance:L(l(r)?r.channelTolerance:void 0,"Shader parity channelTolerance",0,255,8),maxDiffRatio:Ke(l(r)?r.maxDiffRatio:void 0,"Shader parity maxDiffRatio",.01)},bridge:{legacyLab:l(n)&&n.legacyLab===true,...typeof i=="string"?{deterministicModule:i}:{}},readiness:{...typeof a=="string"?{selector:a}:{},...typeof c=="string"?{global:c}:{}},publicDir:Ge(e.publicDir,"Shader publicDir","public"),allowLiveBuilds:e.allowLiveBuilds!==false}}o(we,"parseShaderToolConfig");async function Xe(e=process.cwd()){let t=b.resolve(e);for(;;){if(await C(b.join(t,Je))||await C(b.join(t,"three-blocks.json")))return realpath(t);let r=b.join(t,"package.json");if(await C(r)){let i=await _(t,r,$.packageJson,"Project package.json"),s;try{s=JSON.parse(i.data.toString("utf8"));}catch{throw new Error(`Project package.json is not valid JSON: ${r}.`)}if(l(s)&&[s.dependencies,s.devDependencies,s.peerDependencies,s.optionalDependencies].filter(l).some(f=>typeof f.three=="string"||typeof f["three-blocks"]=="string"||typeof f["@three-blocks/devtools"]=="string"))return realpath(t)}let n=b.dirname(t);if(n===t)throw new Error(`No Three Blocks shader project found from ${JSON.stringify(b.resolve(e))}; add Three.js to package.json or pass --root.`);t=n;}}o(Xe,"findShaderProjectRoot");async function ke(e){let t=await realpath(e),r=b.join(t,Je);if(await C(r)){let i=await _(t,r,$.metadata,"Shader configuration");return we(JSON.parse(i.data.toString("utf8")))}let n=b.join(t,"three-blocks.json");if(await C(n)){let i=ze(JSON.parse(await readFile(n,"utf8")));return we({schemaVersion:1,backend:"both",scenes:[{key:i.template,url:"/",requiresText:i.features.text}]})}return we(Ot)}o(ke,"loadShaderToolConfig");function Y(e,t="webgpu"){if(/^0\.185\./u.test(e))return t==="webgl"?THREE_WEBGL_R185_COMPATIBILITY:THREE_WEBGPU_R185_COMPATIBILITY;if(e===THREE_R186DEV_VERSION&&t==="webgpu")return THREE_WEBGPU_R186DEV_COMPATIBILITY;throw new Error(`Three.js ${e} is outside the supported shader compatibility contracts.`)}o(Y,"shaderCompatibilityForThree");var X="0.1.0";var me=60,Ut="timing.local.json",Wt="timing.json";var pe=4096,Jt=4096;function Re(e,t,r=8192){if(typeof e!="string"||e.length===0||e.length>r||/[\u0000\u007f]/u.test(e))throw new Error(`${t} must be a bounded non-empty string.`);return e}o(Re,"boundedString");function w(e,t,r=true){if(typeof e!="number"||!Number.isFinite(e)||e<0||r&&!Number.isSafeInteger(e))throw new Error(`${t} must be a non-negative ${r?"integer":"finite number"}.`);return e}o(w,"nonNegativeNumber");function qt(e){if(!l(e))throw new Error("Shader capture stats are missing.");let t={buildCalls:w(e.buildCalls,"capture stats.buildCalls"),renderBuilds:w(e.renderBuilds,"capture stats.renderBuilds"),computeBuilds:w(e.computeBuilds,"capture stats.computeBuilds"),registeredBuilds:w(e.registeredBuilds,"capture stats.registeredBuilds"),registeredRenderBuilds:w(e.registeredRenderBuilds,"capture stats.registeredRenderBuilds"),registeredComputeBuilds:w(e.registeredComputeBuilds,"capture stats.registeredComputeBuilds"),buildMs:w(e.buildMs,"capture stats.buildMs",false),syncBuildMs:w(e.syncBuildMs,"capture stats.syncBuildMs",false),asyncBuildElapsedMs:w(e.asyncBuildElapsedMs,"capture stats.asyncBuildElapsedMs",false),precompiledSetupMs:w(e.precompiledSetupMs,"capture stats.precompiledSetupMs",false),maxSyncBuildMs:w(e.maxSyncBuildMs??e.syncBuildMs,"capture stats.maxSyncBuildMs",false),maxPrecompiledSetupMs:w(e.maxPrecompiledSetupMs??e.precompiledSetupMs,"capture stats.maxPrecompiledSetupMs",false),hydrationMs:w(e.hydrationMs??0,"capture stats.hydrationMs",false),maxHydrationMs:w(e.maxHydrationMs??e.hydrationMs??0,"capture stats.maxHydrationMs",false),injected:w(e.injected,"capture stats.injected"),injectedRender:w(e.injectedRender,"capture stats.injectedRender"),injectedCompute:w(e.injectedCompute,"capture stats.injectedCompute"),missed:w(e.missed,"capture stats.missed"),missedRender:w(e.missedRender,"capture stats.missedRender"),missedCompute:w(e.missedCompute,"capture stats.missedCompute"),...Array.isArray(e.missedKeys)&&e.missedKeys.every(r=>typeof r=="string")?{missedKeys:e.missedKeys.slice(0,pe)}:{}};if(t.renderBuilds+t.computeBuilds!==t.buildCalls||t.registeredRenderBuilds+t.registeredComputeBuilds!==t.registeredBuilds||t.injectedRender+t.injectedCompute!==t.injected||t.missedRender+t.missedCompute!==t.missed||t.registeredBuilds>t.buildCalls||Math.abs(t.syncBuildMs+t.asyncBuildElapsedMs-t.buildMs)>.001||t.maxSyncBuildMs>t.syncBuildMs+.001||t.maxPrecompiledSetupMs>t.precompiledSetupMs+.001||t.maxHydrationMs>t.hydrationMs+.001)throw new Error("Shader capture stats totals are inconsistent.");return t}o(qt,"captureStats");function Gt(e){if(!Array.isArray(e)||e.length>pe)throw new Error("Shader capture skipped builds are invalid.");return e.map((t,r)=>{if(!l(t)||t.kind!=="render"&&t.kind!=="compute")throw new Error(`Shader capture skipped build ${r} is invalid.`);return {kind:t.kind,name:Re(t.name,`skipped build ${r} name`,512),reason:Re(t.reason,`skipped build ${r} reason`)}})}o(Gt,"skippedBuilds");function Kt(e){let t=0,r=0,n=0,i=0;for(let s of Object.values(e.entries)){let a=e.states[s];a!==void 0&&((a.vertex!==null||a.fragment!==null)&&t++,a.vertex!==null&&r++,a.fragment!==null&&n++,a.compute!==null&&i++);}return {render:t,vertex:r,fragment:n,compute:i}}o(Kt,"shaderCoverage");function Yt(e,t){if(!l(e))throw new Error("Shader capture payload must be an object.");if(e.scene!==t.scene)throw new Error(`Shader capture scene does not match "${t.scene}".`);if(e.protocolVersion!==2)throw new Error("Shader capture protocolVersion must be 2.");let r=t.backend??"webgpu",n=Y(t.runtime.three,r);if(e.compatibility!==n)throw new Error(`Shader capture compatibility must be "${n}".`);if(!l(e.entries))throw new Error("Shader capture entries must be an object.");if(typeof e.requiresSetup!="boolean")throw new Error("Shader capture requiresSetup must be boolean.");let i=Object.keys(e.entries).length;if(i>pe)throw new Error(`Shader capture must contain at most ${pe} entries.`);if(!Array.isArray(e.errors)||e.errors.length>Jt)throw new Error("Shader capture errors are invalid.");let s=e.errors.map((g,u)=>Re(g,`capture error ${u}`,64*1024));if(s.length>0)throw new Error(`Shader capture failed:
|
|
1
|
+
import {realpath,readFile,mkdir,readdir,unlink,lstat,open,rename,rm}from'fs/promises';import b from'path';import {parsePrecompiledManifest,SHADER_HYDRATION_SCHEMA_VERSION,SHADER_RECIPE_SCHEMA_VERSION,SHADER_ADDRESS_SCHEMA_VERSION,PRECOMPILED_MANIFEST_VERSION,THREE_WEBGL_R185_COMPATIBILITY,THREE_WEBGPU_R185_COMPATIBILITY,THREE_R186DEV_VERSION,THREE_WEBGPU_R186DEV_COMPATIBILITY}from'three-blocks/shaders';import {createHash,randomUUID}from'crypto';import {createRequire}from'module';var kt=Object.defineProperty;var o=(e,t)=>kt(e,"name",{value:t,configurable:true});var $=Object.freeze({metadata:1024*1024,receipt:2*1024*1024,manifest:32*1024*1024,semanticInput:8*1024*1024,semanticTotal:64*1024*1024,metrics:8*1024*1024,texture:128*1024*1024,packageJson:1024*1024});function De(e){return typeof e=="object"&&e!==null&&"code"in e&&typeof e.code=="string"?e.code:void 0}o(De,"errorCode");function I(e){return createHash("sha256").update(e).digest("hex")}o(I,"sha256");async function C(e){try{return await lstat(e),!0}catch(t){if(De(t)==="ENOENT")return false;throw t}}o(C,"pathExists");function v(e,t){let r=b.relative(e,t);return r===""||!b.isAbsolute(r)&&r!==".."&&!r.startsWith(`..${b.sep}`)}o(v,"isWithin");function z(e){return JSON.stringify(e)}o(z,"displayPath");async function Fe(e,t,r){let n=await open(e,"r");try{let[i,s,a]=await Promise.all([lstat(e),n.stat(),realpath(e)]);if(i.isSymbolicLink())throw new Error(`${r} must not be a symbolic link: ${z(e)}.`);if(!s.isFile())throw new Error(`${r} must be a regular file: ${z(e)}.`);if(s.size>t)throw new Error(`${r} exceeds the ${t}-byte inspection limit: ${z(e)}.`);let c=await n.readFile();if(c.byteLength>t)throw new Error(`${r} grew beyond the ${t}-byte inspection limit while being read.`);return {path:a,data:c}}finally{await n.close();}}o(Fe,"readBoundedRegularFile");async function ce(e,t){let r=b.dirname(e);await mkdir(r,{recursive:true});try{if((await lstat(e)).isSymbolicLink())throw new Error(`Atomic write target must not be a symbolic link: ${z(e)}.`)}catch(s){if(De(s)!=="ENOENT")throw s}let n=b.join(r,`.${b.basename(e)}.${process.pid}.${randomUUID()}.tmp`),i;try{i=await open(n,"wx",384),await i.writeFile(t),await i.sync(),await i.close(),i=void 0,await rename(n,e);}finally{await i?.close().catch(()=>{}),await rm(n,{force:true});}}o(ce,"writeAtomicRegularFile");async function ye(e,t,r){return Fe(e,t,r)}o(ye,"readExternalRegularFile");async function U(e,t,r){let n=b.resolve(e),i=b.resolve(t);if(!v(n,i))throw new Error(`${r} escapes its allowed directory.`);let s=await lstat(i);if(s.isSymbolicLink())throw new Error(`${r} must not be a symbolic link.`);if(!s.isDirectory())throw new Error(`${r} must be a directory.`);let[a,c]=await Promise.all([realpath(n),realpath(i)]);if(!v(a,c))throw new Error(`${r} resolves outside its allowed directory.`);return c}o(U,"canonicalDirectoryWithin");async function B(e,t,r,n){let i=b.resolve(e),s=b.resolve(t);if(!v(i,s)||i===s)throw new Error(`${n} escapes its allowed directory.`);let a=await Fe(s,r,n),c=await realpath(i);if(!v(c,a.path)||c===a.path)throw new Error(`${n} resolves outside its allowed directory.`);return a}o(B,"readRegularFileWithin");async function Ve(e,t,r,n=8192){let s=[await U(e,t,"Inspected directory")],a=[],c=0;for(;s.length>0;){let f=s.shift();if(f===void 0)break;let m=(await readdir(f,{withFileTypes:true})).sort((h,d)=>h.name.localeCompare(d.name));for(let h of m){if(c+=1,c>n)throw new Error(`Inspected directory exceeds the ${n}-entry limit.`);let d=b.join(f,h.name);if(h.isSymbolicLink())throw new Error(`Inspected directory contains a symbolic link: ${z(b.relative(e,d))}.`);if(h.isDirectory()){s.push(await U(e,d,"Nested inspected directory"));continue}if(h.isFile()&&r(h.name))a.push(d);else if(r(h.name))throw new Error(`Semantic input is not a regular file: ${z(d)}.`)}}return a.sort()}o(Ve,"listRegularFilesRecursively");var ue=/^[a-f0-9]{64}$/,Mt=/^[0-9A-Za-z][0-9A-Za-z.+_-]{0,127}$/,He=/^[a-z0-9][a-z0-9_-]{0,63}$/,ve=/^[0-9A-Za-z][0-9A-Za-z._/-]{0,127}$/;function l(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}o(l,"isRecord");function W(e){return typeof e=="string"&&Mt.test(e)}o(W,"isSafeVersion");function Se(e){if(e.length===0||e.length>512||e.includes("\\")||/[\u0000-\u001f\u007f]/.test(e))return false;let t=e.split("/");return !e.startsWith("/")&&t.every(r=>r.length>0&&r!=="."&&r!=="..")}o(Se,"isSafeRelativePath");function ze(e){if(!l(e)||e.schemaVersion!==2)throw new Error("three-blocks.json must use schemaVersion 2.");if(typeof e.template!="string"||!He.test(e.template))throw new Error("three-blocks.json has an invalid default shader scene key.");if(!Array.isArray(e.layers)||!e.layers.every(t=>typeof t=="string"&&ve.test(t))||new Set(e.layers).size!==e.layers.length)throw new Error("three-blocks.json has invalid layers.");if(e.generator!==void 0&&(!l(e.generator)||typeof e.generator.name!="string"||!ve.test(e.generator.name)||!W(e.generator.version)))throw new Error("three-blocks.json has invalid generator metadata.");if(!l(e.runtime)||!W(e.runtime.three)||!W(e.runtime.threeBlocks))throw new Error("three-blocks.json has invalid runtime versions.");if(!l(e.features)||typeof e.features.text!="boolean")throw new Error("three-blocks.json has invalid feature metadata.");if(!l(e.protocol)||e.protocol.resultFile!==1)throw new Error("three-blocks.json has an unsupported protocol schema.");if(e.artifacts!==void 0){if(!l(e.artifacts)||typeof e.artifacts.shaders!="string"||!["fresh","pending"].includes(e.artifacts.shaders)||typeof e.artifacts.text!="string"||!["fresh","pending","not-applicable"].includes(e.artifacts.text))throw new Error("three-blocks.json has invalid artifact metadata.");if(e.features.text?e.artifacts.text==="not-applicable":e.artifacts.text!=="not-applicable")throw new Error("three-blocks.json text artifact state does not match the text capability.")}return {schemaVersion:2,template:e.template,layers:e.layers,...e.generator===void 0?{}:{generator:{name:e.generator.name,version:e.generator.version}},runtime:{three:e.runtime.three,threeBlocks:e.runtime.threeBlocks},features:{text:e.features.text},...e.artifacts===void 0?{}:{artifacts:{shaders:e.artifacts.shaders,text:e.artifacts.text}},protocol:{resultFile:1}}}o(ze,"parseProjectMetadata");function Ct(e){if(!l(e))throw new Error("Shader coverage is missing.");for(let t of ["render","vertex","fragment","compute"])if(typeof e[t]!="number"||!Number.isSafeInteger(e[t])||e[t]<0)throw new Error(`Shader coverage.${t} must be a non-negative integer.`);return e}o(Ct,"parseCoverage");function It(e,t){if(!l(e))throw new Error(`Shader receipt inputs for "${t}" are invalid.`);let r=Object.entries(e);if(r.length===0||r.length>4096)throw new Error(`Shader receipt inputs for "${t}" must contain between 1 and 4096 files.`);for(let[n,i]of r)if(!Se(n)||typeof i!="string"||!ue.test(i))throw new Error(`Shader receipt input for "${t}" is invalid.`)}o(It,"parseInputs");function le(e){if(!l(e)||e.schemaVersion!==2||!l(e.runtime)||!W(e.runtime.three)||!W(e.runtime.threeBlocks)||typeof e.runtime.threeBlocksShaderClosure!="string"||!ue.test(e.runtime.threeBlocksShaderClosure)||!l(e.scenes))throw new Error("Shader meta.json does not match receipt schema 2.");if(e.runtime.capture!==void 0&&(!l(e.runtime.capture)||typeof e.runtime.capture.userAgent!="string"||e.runtime.capture.userAgent.length>1024||typeof e.runtime.capture.adapter!="string"||e.runtime.capture.adapter.length>1024||!Array.isArray(e.runtime.capture.features)||e.runtime.capture.features.length>256||!e.runtime.capture.features.every(r=>typeof r=="string"&&r.length>0&&r.length<=128)))throw new Error("Shader meta.json has invalid browser capture provenance.");let t=Object.entries(e.scenes);if(t.length===0)throw new Error("Shader meta.json contains no scenes.");for(let[r,n]of t){let i=r.endsWith(".webgl")?"webgl":"webgpu",s=i==="webgl"?r.slice(0,-6):r;if(!He.test(s)||!l(n)||n.backend!==void 0&&n.backend!==i||typeof n.artifact!="string"||!Se(n.artifact)||!n.artifact.endsWith(`.${i}.ts`)||typeof n.artifactHash!="string"||!ue.test(n.artifactHash))throw new Error(`Shader receipt for "${r}" is invalid.`);if(n.asset===void 0!=(n.assetHash===void 0)||n.asset!==void 0&&(typeof n.asset!="string"||!Se(n.asset)||!n.asset.endsWith(".json")||typeof n.assetHash!="string"||!ue.test(n.assetHash)))throw new Error(`Shader static asset receipt for "${r}" is invalid.`);if(It(n.inputs,r),Ct(n.coverage),n.bytes!==void 0&&(!Number.isSafeInteger(n.bytes)||Number(n.bytes)<0))throw new Error(`Shader receipt byte count for "${r}" is invalid.`);if(n.skipped!==void 0&&(!l(n.skipped)||!Number.isSafeInteger(n.skipped.render)||Number(n.skipped.render)<0||!Number.isSafeInteger(n.skipped.compute)||Number(n.skipped.compute)<0))throw new Error(`Shader receipt skipped-build counts for "${r}" are invalid.`)}if(e.tool!==void 0&&(!l(e.tool)||e.tool.name!=="@three-blocks/devtools"||!W(e.tool.version)||typeof e.tool.compatibility!="string"||!Number.isSafeInteger(e.tool.transform)||!Number.isSafeInteger(e.tool.address)||!Number.isSafeInteger(e.tool.recipe)||!Number.isSafeInteger(e.tool.hydration)))throw new Error("Shader meta.json has invalid tool compatibility metadata.");if(l(e.tool)&&e.tool.compatibilities!==void 0&&(!l(e.tool.compatibilities)||Object.entries(e.tool.compatibilities).some(([r,n])=>r!=="webgpu"&&r!=="webgl"||typeof n!="string"||n.length===0)))throw new Error("Shader meta.json has invalid backend compatibility metadata.");return e}o(le,"parseShaderReceipt");var Je="three-blocks.shaders.json",Ee=".three-blocks/shaders";var Bt=/^[a-z0-9][a-z0-9_-]{0,63}$/u,Pt=/^[A-Za-z_$][A-Za-z0-9_$]*(?:\.[A-Za-z_$][A-Za-z0-9_$]*)*$/u,Ue=64,We=64,Ot={schemaVersion:1,backend:"both",scenes:[{key:"default",url:"/"}]};function qe(e="both"){return e==="both"?["webgpu","webgl"]:[e]}o(qe,"shaderBackends");function J(e,t){return e.backend===void 0?t:t.filter(r=>r===e.backend)}o(J,"shaderSceneBackends");function K(e,t){return t==="webgpu"?e:`${e}.webgl`}o(K,"shaderReceiptKey");function Ge(e,t,r){if(e===void 0)return r;if(typeof e!="string"||e.length===0||e.length>512||b.isAbsolute(e)||/[\u0000-\u001f\u007f]/u.test(e))throw new Error(`${t} must be a bounded project-relative directory.`);let n=b.posix.normalize(e.replaceAll("\\","/")).replace(/\/+$/u,"");if(n==="."||n===".."||n.startsWith("../"))throw new Error(`${t} must stay inside the project.`);return n}o(Ge,"safeProjectDirectory");function Nt(e,t){let r=Ge(e,t,"");if(typeof e!="string"||e.endsWith("/"))throw new Error(`${t} must be a project-relative file.`);return r}o(Nt,"safeProjectFile");function L(e,t,r,n,i){if(e===void 0)return i;if(!Number.isSafeInteger(e)||Number(e)<r||Number(e)>n)throw new Error(`${t} must be an integer in ${r}...${n}.`);return Number(e)}o(L,"boundedInteger");function Ke(e,t,r){if(e===void 0)return r;if(typeof e!="number"||!Number.isFinite(e)||e<0||e>1)throw new Error(`${t} must be a finite ratio in 0...1.`);return e}o(Ke,"finiteRatio");function Ye(e,t){if(typeof e!="string"||e.length===0||e.length>2048||/[\u0000-\u001f\u007f]/u.test(e))throw new Error(`${t} must be a bounded project-relative URL.`);let r;try{r=new URL(e,"http://three-blocks.invalid/");}catch{throw new Error(`${t} is not a valid URL.`)}if(r.origin!=="http://three-blocks.invalid"||r.hash.length>0)throw new Error(`${t} must stay within the project and must not contain a fragment.`);return `${r.pathname}${r.search}`}o(Ye,"safeBrowserUrl");function Lt(e){if(!Array.isArray(e)||e.length===0||e.length>Ue)throw new Error(`Shader config scenes must contain 1...${Ue} entries.`);let t=new Set;return e.map((r,n)=>{if(!l(r)||typeof r.key!="string"||!Bt.test(r.key))throw new Error(`Shader config scene ${n} has an invalid key.`);if(t.has(r.key))throw new Error(`Shader config scene key "${r.key}" is duplicated.`);t.add(r.key);let i=r.parityFrames,s=r.maxDiffRatio;if(r.inputs!==void 0&&(!Array.isArray(r.inputs)||r.inputs.length===0||r.inputs.length>We))throw new Error(`Shader config scene "${r.key}" inputs must contain 1...${We} files.`);let a=r.inputs===void 0?void 0:r.inputs.map((c,f)=>Nt(c,`Shader config scene "${r.key}" input ${f}`));if(a!==void 0&&new Set(a).size!==a.length)throw new Error(`Shader config scene "${r.key}" inputs must be unique.`);if(r.runtimeMotion!==void 0&&typeof r.runtimeMotion!="boolean")throw new Error(`Shader config scene "${r.key}" runtimeMotion must be a boolean.`);if(r.backend!==void 0&&r.backend!=="webgpu"&&r.backend!=="webgl")throw new Error(`Shader config scene "${r.key}" backend must be "webgpu" or "webgl".`);return {key:r.key,url:Ye(r.url,`Shader config scene "${r.key}" URL`),...r.backend===void 0?{}:{backend:r.backend},requiresText:r.requiresText===true,...a===void 0?{}:{inputs:a},...i===void 0?{}:{parityFrames:L(i,`Shader config scene "${r.key}" parityFrames`,0,1e4,0)},...s===void 0?{}:{maxDiffRatio:Ke(s,`Shader config scene "${r.key}" maxDiffRatio`,.01)},...r.runtimeMotion===true?{runtimeMotion:true}:{}}})}o(Lt,"parseScenes");function we(e){if(!l(e)||e.schemaVersion!==void 0&&e.schemaVersion!==1)throw new Error("Shader config must use schemaVersion 1.");let t=e.viewport;if(t!==void 0&&!l(t))throw new Error("Shader config viewport must be an object.");let r=e.parity;if(r!==void 0&&!l(r))throw new Error("Shader config parity must be an object.");let n=e.bridge;if(n!==void 0&&!l(n))throw new Error("Shader config bridge must be an object.");let i=l(n)?n.deterministicModule:void 0;i!==void 0&&Ye(i,"Shader deterministic module");let s=e.readiness;if(s!==void 0&&!l(s))throw new Error("Shader config readiness must be an object.");let a=l(s)?s.selector:void 0;if(a!==void 0&&(typeof a!="string"||a.length===0||a.length>512||/[\u0000-\u001f\u007f]/u.test(a)))throw new Error("Shader readiness selector must be a bounded, non-empty CSS selector.");let c=l(s)?s.global:void 0;if(c!==void 0&&(typeof c!="string"||!Pt.test(c)))throw new Error("Shader readiness global must be a dot-separated JavaScript property path.");if(e.backend!==void 0&&e.backend!=="webgpu"&&e.backend!=="webgl"&&e.backend!=="both")throw new Error('Shader config backend must be "webgpu", "webgl", or "both".');let f=L(e.timeoutMs,"Shader timeoutMs",1e3,15*6e4,24e4);return {schemaVersion:1,backend:e.backend??"both",scenes:Lt(e.scenes),settleFrames:L(e.settleFrames,"Shader settleFrames",0,1e4,60),settleTimeoutMs:L(e.settleTimeoutMs,"Shader settleTimeoutMs",1e3,15*6e4,3e4),browserRelaunchScenes:L(e.browserRelaunchScenes,"Shader browserRelaunchScenes",1,64,8),timeoutMs:f,maxTimeoutMs:Math.max(f,L(e.maxTimeoutMs,"Shader maxTimeoutMs",1e3,15*6e4,f)),viewport:{width:L(l(t)?t.width:void 0,"Shader viewport width",64,8192,1024),height:L(l(t)?t.height:void 0,"Shader viewport height",64,8192,640)},parity:{frames:L(l(r)?r.frames:void 0,"Shader parity frames",0,1e4,90),channelTolerance:L(l(r)?r.channelTolerance:void 0,"Shader parity channelTolerance",0,255,8),maxDiffRatio:Ke(l(r)?r.maxDiffRatio:void 0,"Shader parity maxDiffRatio",.01)},bridge:{legacyLab:l(n)&&n.legacyLab===true,...typeof i=="string"?{deterministicModule:i}:{}},readiness:{...typeof a=="string"?{selector:a}:{},...typeof c=="string"?{global:c}:{}},publicDir:Ge(e.publicDir,"Shader publicDir","public"),allowLiveBuilds:e.allowLiveBuilds!==false}}o(we,"parseShaderToolConfig");async function Xe(e=process.cwd()){let t=b.resolve(e);for(;;){if(await C(b.join(t,Je))||await C(b.join(t,"three-blocks.json")))return realpath(t);let r=b.join(t,"package.json");if(await C(r)){let i=await B(t,r,$.packageJson,"Project package.json"),s;try{s=JSON.parse(i.data.toString("utf8"));}catch{throw new Error(`Project package.json is not valid JSON: ${r}.`)}if(l(s)&&[s.dependencies,s.devDependencies,s.peerDependencies,s.optionalDependencies].filter(l).some(f=>typeof f.three=="string"||typeof f["three-blocks"]=="string"||typeof f["@three-blocks/devtools"]=="string"))return realpath(t)}let n=b.dirname(t);if(n===t)throw new Error(`No Three Blocks shader project found from ${JSON.stringify(b.resolve(e))}; add Three.js to package.json or pass --root.`);t=n;}}o(Xe,"findShaderProjectRoot");async function ke(e){let t=await realpath(e),r=b.join(t,Je);if(await C(r)){let i=await B(t,r,$.metadata,"Shader configuration");return we(JSON.parse(i.data.toString("utf8")))}let n=b.join(t,"three-blocks.json");if(await C(n)){let i=ze(JSON.parse(await readFile(n,"utf8")));return we({schemaVersion:1,backend:"both",scenes:[{key:i.template,url:"/",requiresText:i.features.text}]})}return we(Ot)}o(ke,"loadShaderToolConfig");function Y(e,t="webgpu"){if(/^0\.185\./u.test(e))return t==="webgl"?THREE_WEBGL_R185_COMPATIBILITY:THREE_WEBGPU_R185_COMPATIBILITY;if(e===THREE_R186DEV_VERSION&&t==="webgpu")return THREE_WEBGPU_R186DEV_COMPATIBILITY;throw new Error(`Three.js ${e} is outside the supported shader compatibility contracts.`)}o(Y,"shaderCompatibilityForThree");var X="0.1.0";var me=62,Ut="timing.local.json",Wt="timing.json";var pe=4096,Jt=4096;function Re(e,t,r=8192){if(typeof e!="string"||e.length===0||e.length>r||/[\u0000\u007f]/u.test(e))throw new Error(`${t} must be a bounded non-empty string.`);return e}o(Re,"boundedString");function w(e,t,r=true){if(typeof e!="number"||!Number.isFinite(e)||e<0||r&&!Number.isSafeInteger(e))throw new Error(`${t} must be a non-negative ${r?"integer":"finite number"}.`);return e}o(w,"nonNegativeNumber");function qt(e){if(!l(e))throw new Error("Shader capture stats are missing.");let t={buildCalls:w(e.buildCalls,"capture stats.buildCalls"),renderBuilds:w(e.renderBuilds,"capture stats.renderBuilds"),computeBuilds:w(e.computeBuilds,"capture stats.computeBuilds"),registeredBuilds:w(e.registeredBuilds,"capture stats.registeredBuilds"),registeredRenderBuilds:w(e.registeredRenderBuilds,"capture stats.registeredRenderBuilds"),registeredComputeBuilds:w(e.registeredComputeBuilds,"capture stats.registeredComputeBuilds"),buildMs:w(e.buildMs,"capture stats.buildMs",false),syncBuildMs:w(e.syncBuildMs,"capture stats.syncBuildMs",false),asyncBuildElapsedMs:w(e.asyncBuildElapsedMs,"capture stats.asyncBuildElapsedMs",false),precompiledSetupMs:w(e.precompiledSetupMs,"capture stats.precompiledSetupMs",false),maxSyncBuildMs:w(e.maxSyncBuildMs??e.syncBuildMs,"capture stats.maxSyncBuildMs",false),maxPrecompiledSetupMs:w(e.maxPrecompiledSetupMs??e.precompiledSetupMs,"capture stats.maxPrecompiledSetupMs",false),hydrationMs:w(e.hydrationMs??0,"capture stats.hydrationMs",false),maxHydrationMs:w(e.maxHydrationMs??e.hydrationMs??0,"capture stats.maxHydrationMs",false),injected:w(e.injected,"capture stats.injected"),injectedRender:w(e.injectedRender,"capture stats.injectedRender"),injectedCompute:w(e.injectedCompute,"capture stats.injectedCompute"),missed:w(e.missed,"capture stats.missed"),missedRender:w(e.missedRender,"capture stats.missedRender"),missedCompute:w(e.missedCompute,"capture stats.missedCompute"),...Array.isArray(e.missedKeys)&&e.missedKeys.every(r=>typeof r=="string")?{missedKeys:e.missedKeys.slice(0,pe)}:{}};if(t.renderBuilds+t.computeBuilds!==t.buildCalls||t.registeredRenderBuilds+t.registeredComputeBuilds!==t.registeredBuilds||t.injectedRender+t.injectedCompute!==t.injected||t.missedRender+t.missedCompute!==t.missed||t.registeredBuilds>t.buildCalls||Math.abs(t.syncBuildMs+t.asyncBuildElapsedMs-t.buildMs)>.001||t.maxSyncBuildMs>t.syncBuildMs+.001||t.maxPrecompiledSetupMs>t.precompiledSetupMs+.001||t.maxHydrationMs>t.hydrationMs+.001)throw new Error("Shader capture stats totals are inconsistent.");return t}o(qt,"captureStats");function Gt(e){if(!Array.isArray(e)||e.length>pe)throw new Error("Shader capture skipped builds are invalid.");return e.map((t,r)=>{if(!l(t)||t.kind!=="render"&&t.kind!=="compute")throw new Error(`Shader capture skipped build ${r} is invalid.`);return {kind:t.kind,name:Re(t.name,`skipped build ${r} name`,512),reason:Re(t.reason,`skipped build ${r} reason`)}})}o(Gt,"skippedBuilds");function Kt(e){let t=0,r=0,n=0,i=0;for(let s of Object.values(e.entries)){let a=e.states[s];a!==void 0&&((a.vertex!==null||a.fragment!==null)&&t++,a.vertex!==null&&r++,a.fragment!==null&&n++,a.compute!==null&&i++);}return {render:t,vertex:r,fragment:n,compute:i}}o(Kt,"shaderCoverage");function Yt(e,t){if(!l(e))throw new Error("Shader capture payload must be an object.");if(e.scene!==t.scene)throw new Error(`Shader capture scene does not match "${t.scene}".`);if(e.protocolVersion!==2)throw new Error("Shader capture protocolVersion must be 2.");let r=t.backend??"webgpu",n=Y(t.runtime.three,r);if(e.compatibility!==n)throw new Error(`Shader capture compatibility must be "${n}".`);if(!l(e.entries))throw new Error("Shader capture entries must be an object.");if(typeof e.requiresSetup!="boolean")throw new Error("Shader capture requiresSetup must be boolean.");let i=Object.keys(e.entries).length;if(i>pe)throw new Error(`Shader capture must contain at most ${pe} entries.`);if(!Array.isArray(e.errors)||e.errors.length>Jt)throw new Error("Shader capture errors are invalid.");let s=e.errors.map((g,u)=>Re(g,`capture error ${u}`,64*1024));if(s.length>0)throw new Error(`Shader capture failed:
|
|
2
2
|
- ${s.join(`
|
|
3
3
|
- `)}`);let a=Gt(e.skipped);if(i===0&&(r!=="webgl"||a.length===0))throw new Error("Shader capture must contain an entry unless WebGL explicitly skipped every live build.");let c=qt(e.stats),f=l(e.timing)?e.timing:void 0,m=f===void 0?void 0:Object.fromEntries(["launch","firstRequest","readiness","lastBuild","settled","posted"].flatMap(g=>{let u=f[g];if(u===void 0)return [];if(typeof u!="number"||!Number.isFinite(u)||u<0)throw new Error(`Shader capture timing.${g} is invalid.`);return [[g,u]]})),h;if(e.provenance!==void 0){if(!l(e.provenance)||typeof e.provenance.userAgent!="string"||e.provenance.userAgent.length>1024||typeof e.provenance.adapter!="string"||e.provenance.adapter.length>1024||!Array.isArray(e.provenance.features)||e.provenance.features.length>256||!e.provenance.features.every(g=>typeof g=="string"&&g.length<=128))throw new Error("Shader capture provenance is invalid.");h={userAgent:e.provenance.userAgent,adapter:e.provenance.adapter,features:[...new Set(e.provenance.features)].sort()};}let d=parsePrecompiledManifest({version:PRECOMPILED_MANIFEST_VERSION,scene:t.scene,three:t.runtime.three,threeBlocks:t.runtime.threeBlocks,runtime:{id:n,address:SHADER_ADDRESS_SCHEMA_VERSION,recipe:SHADER_RECIPE_SCHEMA_VERSION,hydration:SHADER_HYDRATION_SCHEMA_VERSION},...e.automatic===void 0?{}:{automatic:e.automatic},requiresSetup:e.requiresSetup,modules:e.modules,nodes:e.nodes,layouts:e.layouts,attributePlans:e.attributePlans,updatePlans:e.updatePlans,requirementPlans:e.requirementPlans,states:e.states,entries:e.entries,...e.fallbacks===void 0?{}:{fallbacks:e.fallbacks}}),p=Kt(d);if(c.registeredRenderBuilds<p.render||c.registeredComputeBuilds<p.compute)throw new Error("Shader capture did not live-build every distinct registered render/compute entry.");return {scene:t.scene,backend:r,manifest:d,skipped:a,stats:c,coverage:p,...m===void 0?{}:{timing:m},...h===void 0?{}:{provenance:h}}}o(Yt,"validateShaderCapture");function q(e,t=0){let r=" ".repeat(t),n=" ".repeat(t+1);if(Array.isArray(e))return e.length===0?"[]":e.every(s=>s===null||["number","string","boolean"].includes(typeof s))?JSON.stringify(e):`[
|
|
4
4
|
${e.map(s=>`${n}${q(s,t+1)}`).join(`,
|
|
@@ -7,13 +7,13 @@ ${r}]`;if(e!==null&&typeof e=="object"){let s=e,a=Object.keys(s).sort();return a
|
|
|
7
7
|
${a.map(c=>{let f=s[c];return `${n}${JSON.stringify(c)}: ${q(f,t+1)}`}).join(`,
|
|
8
8
|
`)}
|
|
9
9
|
${r}}`}let i=JSON.stringify(e);if(i===void 0)throw new Error("Shader artifact contains a non-serializable value.");return i}o(q,"stableStringify");function Xt(e){return ["// GENERATED FILE \u2014 do not edit by hand.","// Produced by @three-blocks/devtools.","import type { PrecompiledManifest } from 'three-blocks/shaders';","",`export default ${q(e)} satisfies PrecompiledManifest;`,""].join(`
|
|
10
|
-
`)}o(Xt,"serializeShaderManifest");function et(e,t){if(typeof e!="string"||e.length===0||e.length>256||/[\u0000-\u001f\u007f]/u.test(e))throw new Error(`${t} is invalid.`);return e}o(et,"timingLabel");function Zt(e){if(!l(e)||e.schemaVersion!==3||e.source!=="latest-local-capture"&&e.source!=="committed-capture"||typeof e.receiptHash!="string"||!/^[a-f0-9]{64}$/u.test(e.receiptHash)||typeof e.measuredAt!="string"||!Number.isFinite(Date.parse(e.measuredAt))||!l(e.scenes))throw new Error("Shader timing is invalid.");let t={};for(let[n,i]of Object.entries(e.scenes)){if(n.length===0||n.length>128||!l(i))throw new Error("Shader timing scene is invalid.");let s={builds:w(i.builds,`timing ${n}.builds`),setupMeasured:i.setupMeasured===true,liveBuildMs:w(i.liveBuildMs,`timing ${n}.liveBuildMs`,false),precompiledBuildMs:w(i.precompiledBuildMs,`timing ${n}.precompiledBuildMs`,false),avoidedBuildMs:w(i.avoidedBuildMs,`timing ${n}.avoidedBuildMs`,false),runs:w(i.runs,`timing ${n}.runs`),spreadMs:w(i.spreadMs,`timing ${n}.spreadMs`,false)};if(s.runs<1)throw new Error(`Shader timing runs are invalid for scene "${n}".`);if(Math.abs(s.avoidedBuildMs-Math.max(0,s.liveBuildMs-s.precompiledBuildMs))>.001)throw new Error(`Shader timing delta is inconsistent for scene "${n}".`);t[n]=s;}if(Object.keys(t).length===0)throw new Error("Shader timing contains no scenes.");let r={schemaVersion:3,receiptHash:e.receiptHash,measuredAt:e.measuredAt,scenes:t};return e.source==="latest-local-capture"?{...r,source:"latest-local-capture"}:{...r,source:"committed-capture",adapter:et(e.adapter,"Shader timing adapter"),platform:et(e.platform,"Shader timing platform")}}o(Zt,"parseShaderTiming");async function tt(e,t,r,n){let i=b.join(e,r);try{if(!await C(i))return;let s=await lstat(i);if(s.isSymbolicLink()||!s.isFile()||s.size>1024*1024)return;let a=Zt(JSON.parse(await readFile(i,"utf8")));return a.source===n&&a.receiptHash===I(t)?a:void 0}catch{return}}o(tt,"readShaderTimingFile");async function dt(e,t){return await tt(e,t,Ut,"latest-local-capture")??await tt(e,t,Wt,"committed-capture")}o(dt,"readShaderTiming");async function rt(e){if(!await C(e)){await mkdir(e);return}let t=await lstat(e);if(t.isSymbolicLink()||!t.isDirectory())throw new Error(`Shader artifact path is not a real directory: ${e}.`)}o(rt,"assertDirectory");async function Qt(e){let t=b.resolve(e),r=b.join(t,".three-blocks");await rt(r);let n=b.join(r,"shaders");return await rt(n),n}o(Qt,"artifactRoot");async function er(e){let t=await Qt(e.root),r=e.backends??["webgpu"],n=Object.fromEntries(r.map(u=>[u,Y(e.runtime.three,u)])),i=b.resolve(e.root),s=b.resolve(i,e.publicDirectory??"public");if(!v(i,s)||s===i)throw new Error("Shader public directory must stay inside the project root.");let a=b.join(s,"three-blocks","shaders");await mkdir(a,{recursive:true}),await U(i,a,"Shader static-asset directory");let c={},f=[];for(let u of [...e.scenes].sort((R,y)=>R.key.localeCompare(y.key))){let R=e.inputs.get(u.key);if(R===void 0)throw new Error(`Shader input matrix is missing scene "${u.key}".`);for(let y of J(u,r)){let k=K(u.key,y),x=e.captures.get(k);if(x===void 0){let S=e.previousReceipt?.scenes[k];if(S===void 0)continue;let N=await readFile(b.join(t,S.artifact));if(I(N)!==S.artifactHash)throw new Error(`Preserved shader artifact checksum differs for "${k}".`);if(S.asset!==void 0&&S.assetHash!==void 0){let j=await readFile(b.join(s,S.asset));if(I(j)!==S.assetHash)throw new Error(`Preserved static shader manifest checksum differs for "${k}".`)}c[k]={...S,backend:y,inputs:Object.fromEntries(Object.entries(R).sort(([j],[re])=>j.localeCompare(re)))},f.push(S.artifact),S.asset!==void 0&&f.push(b.relative(i,b.join(s,S.asset)).split(b.sep).join("/"));continue}if(x.scene!==u.key||x.backend!==y||x.manifest.scene!==u.key)throw new Error(`Capture matrix scene/backend "${k}" is inconsistent.`);let A=`${u.key}.${y}.ts`,O=Xt(x.manifest);await ce(b.join(t,A),O),f.push(A);let
|
|
11
|
-
`;await ce(b.join(s,
|
|
10
|
+
`)}o(Xt,"serializeShaderManifest");function et(e,t){if(typeof e!="string"||e.length===0||e.length>256||/[\u0000-\u001f\u007f]/u.test(e))throw new Error(`${t} is invalid.`);return e}o(et,"timingLabel");function Zt(e){if(!l(e)||e.schemaVersion!==3||e.source!=="latest-local-capture"&&e.source!=="committed-capture"||typeof e.receiptHash!="string"||!/^[a-f0-9]{64}$/u.test(e.receiptHash)||typeof e.measuredAt!="string"||!Number.isFinite(Date.parse(e.measuredAt))||!l(e.scenes))throw new Error("Shader timing is invalid.");let t={};for(let[n,i]of Object.entries(e.scenes)){if(n.length===0||n.length>128||!l(i))throw new Error("Shader timing scene is invalid.");let s={builds:w(i.builds,`timing ${n}.builds`),setupMeasured:i.setupMeasured===true,liveBuildMs:w(i.liveBuildMs,`timing ${n}.liveBuildMs`,false),precompiledBuildMs:w(i.precompiledBuildMs,`timing ${n}.precompiledBuildMs`,false),avoidedBuildMs:w(i.avoidedBuildMs,`timing ${n}.avoidedBuildMs`,false),runs:w(i.runs,`timing ${n}.runs`),spreadMs:w(i.spreadMs,`timing ${n}.spreadMs`,false)};if(s.runs<1)throw new Error(`Shader timing runs are invalid for scene "${n}".`);if(Math.abs(s.avoidedBuildMs-Math.max(0,s.liveBuildMs-s.precompiledBuildMs))>.001)throw new Error(`Shader timing delta is inconsistent for scene "${n}".`);t[n]=s;}if(Object.keys(t).length===0)throw new Error("Shader timing contains no scenes.");let r={schemaVersion:3,receiptHash:e.receiptHash,measuredAt:e.measuredAt,scenes:t};return e.source==="latest-local-capture"?{...r,source:"latest-local-capture"}:{...r,source:"committed-capture",adapter:et(e.adapter,"Shader timing adapter"),platform:et(e.platform,"Shader timing platform")}}o(Zt,"parseShaderTiming");async function tt(e,t,r,n){let i=b.join(e,r);try{if(!await C(i))return;let s=await lstat(i);if(s.isSymbolicLink()||!s.isFile()||s.size>1024*1024)return;let a=Zt(JSON.parse(await readFile(i,"utf8")));return a.source===n&&a.receiptHash===I(t)?a:void 0}catch{return}}o(tt,"readShaderTimingFile");async function dt(e,t){return await tt(e,t,Ut,"latest-local-capture")??await tt(e,t,Wt,"committed-capture")}o(dt,"readShaderTiming");async function rt(e){if(!await C(e)){await mkdir(e);return}let t=await lstat(e);if(t.isSymbolicLink()||!t.isDirectory())throw new Error(`Shader artifact path is not a real directory: ${e}.`)}o(rt,"assertDirectory");async function Qt(e){let t=b.resolve(e),r=b.join(t,".three-blocks");await rt(r);let n=b.join(r,"shaders");return await rt(n),n}o(Qt,"artifactRoot");async function er(e){let t=await Qt(e.root),r=e.backends??["webgpu"],n=Object.fromEntries(r.map(u=>[u,Y(e.runtime.three,u)])),i=b.resolve(e.root),s=b.resolve(i,e.publicDirectory??"public");if(!v(i,s)||s===i)throw new Error("Shader public directory must stay inside the project root.");let a=b.join(s,"three-blocks","shaders");await mkdir(a,{recursive:true}),await U(i,a,"Shader static-asset directory");let c={},f=[];for(let u of [...e.scenes].sort((R,y)=>R.key.localeCompare(y.key))){let R=e.inputs.get(u.key);if(R===void 0)throw new Error(`Shader input matrix is missing scene "${u.key}".`);for(let y of J(u,r)){let k=K(u.key,y),x=e.captures.get(k);if(x===void 0){let S=e.previousReceipt?.scenes[k];if(S===void 0)continue;let N=await readFile(b.join(t,S.artifact));if(I(N)!==S.artifactHash)throw new Error(`Preserved shader artifact checksum differs for "${k}".`);if(S.asset!==void 0&&S.assetHash!==void 0){let j=await readFile(b.join(s,S.asset));if(I(j)!==S.assetHash)throw new Error(`Preserved static shader manifest checksum differs for "${k}".`)}c[k]={...S,backend:y,inputs:Object.fromEntries(Object.entries(R).sort(([j],[re])=>j.localeCompare(re)))},f.push(S.artifact),S.asset!==void 0&&f.push(b.relative(i,b.join(s,S.asset)).split(b.sep).join("/"));continue}if(x.scene!==u.key||x.backend!==y||x.manifest.scene!==u.key)throw new Error(`Capture matrix scene/backend "${k}" is inconsistent.`);let A=`${u.key}.${y}.ts`,O=Xt(x.manifest);await ce(b.join(t,A),O),f.push(A);let _=`three-blocks/shaders/${u.key}.${y}.json`,F=`${q(x.manifest)}
|
|
11
|
+
`;await ce(b.join(s,_),F),f.push(b.relative(i,b.join(s,_)).split(b.sep).join("/"));let V=x.skipped.filter(S=>S.kind==="render").length,T=x.skipped.length-V;c[k]={backend:y,artifact:A,artifactHash:I(O),asset:_,assetHash:I(F),inputs:Object.fromEntries(Object.entries(R).sort(([S],[N])=>S.localeCompare(N))),coverage:x.coverage,bytes:Buffer.byteLength(O),skipped:{render:V,compute:T}};}}let m=[...e.captures.values()].find(u=>u.provenance!==void 0)?.provenance??e.previousReceipt?.runtime.capture,h={schemaVersion:2,runtime:{...e.runtime,...m===void 0?{}:{capture:m}},tool:{name:"@three-blocks/devtools",version:X,compatibility:n[r[0]??"webgpu"],compatibilities:n,transform:me,address:SHADER_ADDRESS_SCHEMA_VERSION,recipe:SHADER_RECIPE_SCHEMA_VERSION,hydration:SHADER_HYDRATION_SCHEMA_VERSION},scenes:c},d=new Set(f);for(let u of await readdir(t,{withFileTypes:true}))if(!(!/\.(?:webgpu|webgl)\.ts$/u.test(u.name)||d.has(u.name))){if(u.isSymbolicLink()||!u.isFile())throw new Error(`Orphan shader artifact is not a regular file: ${u.name}.`);await unlink(b.join(t,u.name));}let p=new Set(e.scenes.flatMap(u=>J(u,r).map(R=>`${u.key}.${R}.json`))),g=new Set(Object.values(e.previousReceipt?.scenes??{}).map(u=>u.asset===void 0?void 0:b.posix.basename(u.asset)).filter(u=>u!==void 0));try{let u=le(JSON.parse(await readFile(b.join(t,"meta.json"),"utf8")));for(let R of Object.values(u.scenes))R.asset!==void 0&&g.add(b.posix.basename(R.asset));}catch{}for(let u of await readdir(a,{withFileTypes:true}))if(!(!u.name.endsWith(".json")||p.has(u.name))&&g.has(u.name)){if(u.isSymbolicLink()||!u.isFile())throw new Error(`Orphan shader static asset is not a regular file: ${u.name}.`);await unlink(b.join(a,u.name));}return await ce(b.join(t,"meta.json"),`${q(h)}
|
|
12
12
|
`),f.push("meta.json"),{directory:t,receipt:h,files:f}}o(er,"writeShaderArtifacts");var Te=[".ts",".tsx",".mts",".cts",".js",".jsx",".mjs",".cjs",".wgsl",".glsl",".vert",".frag",".json",".css"],je=new Set(Te),xe=/^(?:three-blocks\.shaders\.json|(?:precompile|three-blocks\.shaders)\.config\.(?:cjs|cts|js|mjs|mts|ts))$/u,rr=/(?:^|\/)scene\.(?:cjs|cts|js|jsx|mjs|mts|ts|tsx)$/u,nr=/\b(?:export\s+)?(?:async\s+)?function\s+createScene\b|\bcreateScene\s*=\s*(?:async\s*)?\(/u,ir=/\b(?:[A-Za-z_$][\w$]*\.)*(?:shaders|shaderCache|sceneShaders)\s*\.\s*(?:material|pipeline|compute|container)\s*\(/u,sr=/\b(import|export)(?!\s*\()\s*(type\b\s*)?(?:[^"'();]*?\bfrom\s*)?["']([^"']+)["']/gu,or=/\bimport\s*\(\s*["']([^"']+)["']\s*\)/gu,ar=/\b(?:import|export)(?!\s*\()\s*(?:[^"'();]*?\bfrom\s*)?["']([^"']+)["']|\bimport\s*\(\s*["']([^"']+)["']\s*\)/gu,dr=/^[0-9A-Za-z][0-9A-Za-z.+_-]{0,127}$/u,$e=4096,cr="./shaders";function lt(e,t){let r=b.relative(e,t).split(b.sep).join("/");if(r.length===0||/[\u0000-\u001f\u007f]/u.test(r))throw new Error("Semantic input has an unsafe relative path.");return r}o(lt,"portableRelativePath");function Ae(e,t){try{return new TextDecoder("utf-8",{fatal:!0}).decode(e)}catch{throw new Error(`Shader-relevant source ${JSON.stringify(t)} is not valid UTF-8.`)}}o(Ae,"sourceText");function Ce(e,t){let r="",n="code";for(let i=0;i<e.length;i++){let s=e[i]??"",a=e[i+1]??"";if(n==="code"){if(s==="/"&&a==="/"){r+=" ",n="line-comment",i++;continue}if(s==="/"&&a==="*"){r+=" ",n="block-comment",i++;continue}if(s==="'"||s==='"'||s==="`"){n=s==="'"?"single":s==='"'?"double":"template",r+=t?s:" ";continue}r+=s;continue}if(n==="line-comment"){s===`
|
|
13
13
|
`?(r+=`
|
|
14
14
|
`,n="code"):r+=" ";continue}if(n==="block-comment"){s==="*"&&a==="/"?(r+=" ",n="code",i++):r+=s===`
|
|
15
15
|
`?`
|
|
16
16
|
`:" ";continue}let c=n==="single"?"'":n==="double"?'"':"`";if(s==="\\"&&a.length>0){r+=t?`${s}${a}`:" ",i++;continue}r+=t?s:s===`
|
|
17
17
|
`?`
|
|
18
|
-
`:" ",s===c&&(n="code");}return r}o(Ce,"lexicalSource");function ur(e){let t=new Set,r=Ce(e,true);for(let n of r.matchAll(sr))n[2]===void 0&&n[3]!==void 0&&t.add(n[3]);for(let n of r.matchAll(or))n[1]!==void 0&&t.add(n[1]);return [...t].sort()}o(ur,"importSpecifiers");function lr(e){let t=new Set;for(let r of Ce(e,true).matchAll(ar)){let n=r[1]??r[2];n!==void 0&&t.add(n);}return [...t].sort()}o(lr,"runtimeSpecifiers");function ft(e){return (e.split(/[?#]/u,1)[0]??e).replaceAll("\\","/")}o(ft,"cleanSpecifier");function fr(e,t,r){let n=ft(t),i;if(n.startsWith("./")||n.startsWith("../"))i=b.posix.normalize(b.posix.join(b.posix.dirname(e),n));else if(n.startsWith("@/"))i=`src/${n.slice(2)}`;else if(n.startsWith("/src/"))i=n.slice(1);else return;if(i===".three-blocks"||i.startsWith(".three-blocks/"))return;let s=b.posix.extname(i).toLowerCase(),a=new Set([i]);if(s.length===0||!je.has(s)){for(let c of Te)a.add(`${i}${c}`);for(let c of Te)a.add(`${i}/index${c}`);}else if([".js",".mjs",".cjs",".jsx"].includes(s)){let c=i.slice(0,-s.length);for(let f of [".ts",".tsx",".mts",".cts"])a.add(`${c}${f}`);}return [...a].find(c=>r.has(c))}o(fr,"resolveProjectImport");function pr(e,t){let r=Ce(t,false);return rr.test(e)||nr.test(r)||ir.test(r)}o(pr,"isShaderRoot");async function Ie(e,t){let r=await realpath(e);if(t!==void 0){let d={},p=0;for(let g of t){let u=await
|
|
19
|
-
`);return I(c)}o(mr,"shaderRuntimeClosure");async function Be(e){let[t,r]=await Promise.all([ct(e,"three"),ct(e,"three-blocks")]);return {three:String(t.manifest.version),threeBlocks:String(r.manifest.version),threeBlocksShaderClosure:await mr(r.root,r.manifest)}}o(Be,"readInstalledShaderRuntime");var Z;async function gr(){Z===void 0&&(Z=(async()=>{let t=createRequire(b.join(process.cwd(),"package.json")).resolve("@three-blocks/devtools/browser/shader-capture"),r=b.resolve(b.dirname(t),"../..");return (await _(r,t,$.metadata,"Shader capture browser runtime")).data.toString("utf8")})());let e=Z;try{return await e}catch(t){throw Z===e&&(Z=void 0),t}}o(gr,"loadShaderCaptureRuntimeSource");var pt=4096,Sr=createRequire(import.meta.url),mt,E=new Proxy({},{get(e,t){return mt??=Sr("typescript"),Reflect.get(mt,t)}});function H(e){let t=e;for(;E.isParenthesizedExpression(t)||E.isAsExpression(t)||E.isSatisfiesExpression(t)||E.isNonNullExpression(t);)t=t.expression;return t}o(H,"unwrap");function wr(e){if(E.isIdentifier(e)||E.isStringLiteral(e)||E.isNumericLiteral(e))return e.text}o(wr,"propertyName");function Q(e,t){let r=new Map;for(let n of e.properties){if(!E.isPropertyAssignment(n))throw new Error(`${t} may contain only static property assignments.`);let i=wr(n.name);if(i===void 0||r.has(i))throw new Error(`${t} contains a computed or duplicate property.`);r.set(i,n.initializer);}return r}o(Q,"properties");function ee(e,t){if(e===void 0)throw new Error(`${t} is missing.`);let r=H(e);if(!E.isObjectLiteralExpression(r))throw new Error(`${t} must be a static object literal.`);return r}o(ee,"objectLiteral");function te(e,t){if(e===void 0)throw new Error(`${t} is missing.`);let r=H(e);if(!E.isStringLiteral(r)&&!E.isNoSubstitutionTemplateLiteral(r))throw new Error(`${t} must be a string literal.`);return r.text}o(te,"stringLiteral");function he(e,t){if(e===void 0)throw new Error(`${t} is missing.`);let r=H(e);if(!E.isNumericLiteral(r))throw new Error(`${t} must be a numeric literal.`);return Number(r.text)}o(he,"numericLiteral");function ht(e,t){if(e===void 0)throw new Error(`${t} is missing.`);let r=H(e);if(!E.isArrayLiteralExpression(r))throw new Error(`${t} must be a static array literal.`);return r.elements}o(ht,"arrayLiteral");function br(e,t){if(e===void 0)throw new Error(`${t} is missing.`);let r=H(e);if(r.kind===E.SyntaxKind.NullKeyword)return null;if(!E.isNumericLiteral(r))throw new Error(`${t} must be null or a numeric literal.`);return Number(r.text)}o(br,"numericOrNullLiteral");function Er(e){return e.parseDiagnostics??[]}o(Er,"parseDiagnostics");function gt(e,t,r,n){let i=E.createSourceFile(t,e,E.ScriptTarget.Latest,true,E.ScriptKind.TS),s=Er(i);if(s.length>0)throw new Error(`Shader manifest is not valid TypeScript: ${E.flattenDiagnosticMessageText(s[0]?.messageText??"parse error"," ")}`);let a=i.statements.filter(E.isExportAssignment).filter(y=>!y.isExportEquals);if(a.length!==1)throw new Error("Shader manifest must contain exactly one default export.");let c=Q(ee(a[0]?.expression,"Shader manifest default export"),"Shader manifest"),f=c.get("version");if(f===void 0||!E.isNumericLiteral(H(f))||Number(H(f).getText(i))!==3)throw new Error("Shader manifest version must be the numeric literal 3.");if(te(c.get("scene"),"Shader manifest scene")!==r)throw new Error(`Shader manifest scene does not match "${r}".`);let m=c.get("runtime"),d=(n?.compatibility??(m===void 0?"":te(Q(ee(m,"Shader manifest runtime"),"Shader manifest runtime").get("id"),"Shader manifest runtime id"))).startsWith("three-webgl-");if(n){if(te(c.get("three"),"Shader manifest Three.js version")!==n.three||te(c.get("threeBlocks"),"Shader manifest Three Blocks version")!==n.threeBlocks)throw new Error("Shader manifest runtime versions do not match its receipt.");let y=Q(ee(c.get("runtime"),"Shader manifest runtime"),"Shader manifest runtime");if(te(y.get("id"),"Shader manifest runtime id")!==n.compatibility||he(y.get("address"),"Shader manifest address schema")!==n.address||he(y.get("recipe"),"Shader manifest recipe schema")!==n.recipe||he(y.get("hydration"),"Shader manifest hydration schema")!==n.hydration)throw new Error("Shader manifest runtime compatibility schemas do not match its receipt.")}let p=Q(ee(c.get("entries"),"Shader manifest entries"),"Shader manifest entries");if(p.size===0&&!d||p.size>pt)throw new Error(`Shader manifest must contain ${d?"0":"1"}...${pt} entries.`);let g=ht(c.get("modules"),"Shader manifest modules").map((y,k)=>{let x=H(y);if(!E.isStringLiteral(x)&&!E.isNoSubstitutionTemplateLiteral(x))throw new Error(`Shader manifest module ${k} must be a shader string literal.`);if(x.text.length===0)throw new Error(`Shader manifest module ${k} is empty.`);return x.text}),u=ht(c.get("states"),"Shader manifest states").map((y,k)=>{let x=Q(ee(y,`Shader manifest state ${k}`),`Shader manifest state ${k}`),A=o((V,T)=>{let S=br(x.get(V),`Shader manifest state ${k} ${V}`);if(S===null)return false;let N=g[S];if(N===void 0||!d&&!N.includes(T))throw new Error(`Shader manifest state ${k} ${V} does not reference a ${T} module.`);return true},"moduleAt"),O=A("vertex","@vertex"),B=A("fragment","@fragment"),F=A("compute","@compute");if(F&&(O||B))throw new Error(`Shader manifest state ${k} mixes render and compute stages.`);if(!F&&!O&&!B)throw new Error(`Shader manifest state ${k} contains no shader stage.`);return {vertex:O,fragment:B,compute:F}}),R={render:0,vertex:0,fragment:0,compute:0};for(let[y,k]of p){if(y.length===0||/[\u0000-\u001f\u007f]/.test(y))throw new Error("Shader manifest contains an invalid entry key.");let x=he(k,`Shader manifest entry "${y}"`),A=u[x];if(A===void 0)throw new Error(`Shader manifest entry "${y}" references an absent state.`);(A.vertex||A.fragment)&&(R.render+=1),A.vertex&&(R.vertex+=1),A.fragment&&(R.fragment+=1),A.compute&&(R.compute+=1);}return R}o(gt,"inspectPrecompiledManifest");function kr(e,t){return e.render===t.render&&e.vertex===t.vertex&&e.fragment===t.fragment&&e.compute===t.compute}o(kr,"sameCoverage");function Rr(e){let t=e.some(n=>n.state==="invalid")?"invalid":e.some(n=>n.state==="missing")?"missing":e.some(n=>n.state==="stale")?"stale":"fresh",r=e.filter(n=>n.state===t);return {state:t,reason:t==="fresh"?`${e.length} configured shader scene${e.length===1?" is":"s are"} fresh.`:r.map(n=>`${n.scene} (${n.backend}): ${n.reason}`).join("; ")}}o(Rr,"classifyMatrix");function xr(e,t,r){let n=e.tool;if(!n)return "Shader receipt has no public tool compatibility metadata.";if((n.compatibilities?.[r]??n.compatibility)!==t)return "Shader receipt targets a different runtime compatibility contract.";if(n.transform!==me)return "Shader receipt uses a different provider transform version.";if(n.address!==SHADER_ADDRESS_SCHEMA_VERSION||n.recipe!==SHADER_RECIPE_SCHEMA_VERSION||n.hydration!==SHADER_HYDRATION_SCHEMA_VERSION)return "Shader receipt uses incompatible address, recipe, or hydration schemas."}o(xr,"exactToolCompatibility");function Tr(e,t){let r=Object.keys(t).filter(s=>Object.hasOwn(e,s)&&e[s]!==t[s]),n=Object.keys(t).filter(s=>!Object.hasOwn(e,s)),i=Object.keys(e).filter(s=>!Object.hasOwn(t,s));return {...r.length>0?{changedInputs:r}:{},...n.length>0?{addedInputs:n}:{},...i.length>0?{removedInputs:i}:{}}}o(Tr,"inputChanges");async function jr(e=process.cwd(),t,r){let n=await Xe(e),i=await ke(n),s=qe(r??i.backend),a=i.scenes.flatMap(m=>J(m,s).map(h=>({scene:m,backend:h,key:K(m.key,h)}))),c=b.join(n,Ee),f=o(()=>({schemaVersion:1,root:n,state:"missing",reason:`${Ee}/meta.json is absent.`,scenes:a.map(({scene:m,backend:h})=>({scene:m.key,backend:h,state:"missing",reason:"No committed shader receipt."}))}),"missing");if(!await C(c)||!await C(b.join(c,"meta.json")))return f();try{let m=await U(n,c,"Shader artifact directory"),h=await _(m,b.join(m,"meta.json"),$.receipt,"Shader receipt"),d=le(JSON.parse(h.data.toString("utf8"))),p=await dt(m,h.data),g=t??await Be(n),u=new Set(i.scenes.flatMap(T=>J(T,["webgpu","webgl"]).map(S=>K(T.key,S)))),y=Object.keys(d.scenes).filter(T=>!u.has(T));if(y.length>0)throw new Error(`Shader receipt contains unconfigured scenes: ${y.join(", ")}.`);let k=d.runtime.three!==g.three||d.runtime.threeBlocks!==g.threeBlocks,x=d.runtime.threeBlocksShaderClosure!==g.threeBlocksShaderClosure,A=d.tool?.version!==X,O=b.join(n,i.publicDir??"public"),B=[];for(let{scene:T,backend:S,key:N}of a){let j=d.scenes[N];if(!j){B.push({scene:T.key,backend:S,state:"missing",reason:"Scene/backend is absent from the complete receipt matrix."});continue}let re=Y(g.three,S),Pe=xr(d,re,S);if(Pe)throw new Error(`${N}: ${Pe}`);let ne=await _(m,b.join(m,j.artifact),$.manifest,"Shader manifest");if(I(ne.data)!==j.artifactHash)throw new Error(`Shader artifact checksum differs for scene "${T.key}".`);if(j.asset!==void 0&&j.assetHash!==void 0){let Et=await _(O,b.join(O,j.asset),$.manifest,"Static shader manifest");if(I(Et.data)!==j.assetHash)throw new Error(`Static shader manifest checksum differs for scene "${T.key}".`)}if(j.bytes!==void 0&&j.bytes!==ne.data.byteLength)throw new Error(`Shader artifact byte count differs for scene "${T.key}".`);let ie=gt(ne.data.toString("utf8"),ne.path,T.key,{three:d.runtime.three,threeBlocks:d.runtime.threeBlocks,compatibility:re,address:SHADER_ADDRESS_SCHEMA_VERSION,recipe:SHADER_RECIPE_SCHEMA_VERSION,hydration:SHADER_HYDRATION_SCHEMA_VERSION});if(!kr(ie,j.coverage))throw new Error(`Shader coverage differs for scene "${T.key}".`);if(S==="webgpu"&&!i.allowLiveBuilds&&j.skipped&&j.skipped.render+j.skipped.compute>0)throw new Error(`Scene "${T.key}" contains skipped live builds but allowLiveBuilds is false.`);let bt=await Ie(n,T.inputs),se=Tr(j.inputs,bt),oe=(se.changedInputs?.length??0)+(se.addedInputs?.length??0)+(se.removedInputs?.length??0),Oe=k||x||A||oe>0,Ne=p?.scenes[N],ge=Ne===void 0||p===void 0?void 0:{...Ne,schemaVersion:p.schemaVersion,measuredAt:p.measuredAt,source:p.source,...p.source==="committed-capture"?{adapter:p.adapter,platform:p.platform}:{}};B.push({scene:T.key,backend:S,state:Oe?"stale":"fresh",reason:k?"Installed runtime versions differ from the receipt.":x?"Installed three-blocks/shaders runtime closure differs from the receipt.":A?`Receipt was generated by @three-blocks/devtools ${d.tool?.version??"unknown"}.`:oe>0?`${oe} semantic shader input${oe===1?"":"s"} changed.`:"Manifest, runtime, schemas, transform, and semantic inputs match.",coverage:ie,...!Oe&&ge!==void 0&&ge.builds===ie.render+ie.compute?{timing:ge}:{},...se});}let F=Rr(B),V=F.state==="fresh"&&p!==void 0&&B.every(T=>T.timing!==void 0)?p:void 0;return {schemaVersion:1,root:n,...F,scenes:B,runtime:g,receipt:d,...V===void 0?{}:{timing:V}}}catch(m){let h=m instanceof Error?m.message:String(m);return {schemaVersion:1,root:n,state:"invalid",reason:h,scenes:a.map(({scene:d,backend:p})=>({scene:d.key,backend:p,state:"invalid",reason:h}))}}}o(jr,"inspectShaderMatrix");export{me as SHADER_PROVIDER_TRANSFORM_VERSION,jr as inspectShaderMatrix,gr as loadShaderCaptureRuntimeSource,ke as loadShaderToolConfig,Be as readInstalledShaderRuntime,Ie as snapshotShaderInputs,q as stableStringify,Yt as validateShaderCapture,er as writeShaderArtifacts};
|
|
18
|
+
`:" ",s===c&&(n="code");}return r}o(Ce,"lexicalSource");function ur(e){let t=new Set,r=Ce(e,true);for(let n of r.matchAll(sr))n[2]===void 0&&n[3]!==void 0&&t.add(n[3]);for(let n of r.matchAll(or))n[1]!==void 0&&t.add(n[1]);return [...t].sort()}o(ur,"importSpecifiers");function lr(e){let t=new Set;for(let r of Ce(e,true).matchAll(ar)){let n=r[1]??r[2];n!==void 0&&t.add(n);}return [...t].sort()}o(lr,"runtimeSpecifiers");function ft(e){return (e.split(/[?#]/u,1)[0]??e).replaceAll("\\","/")}o(ft,"cleanSpecifier");function fr(e,t,r){let n=ft(t),i;if(n.startsWith("./")||n.startsWith("../"))i=b.posix.normalize(b.posix.join(b.posix.dirname(e),n));else if(n.startsWith("@/"))i=`src/${n.slice(2)}`;else if(n.startsWith("/src/"))i=n.slice(1);else return;if(i===".three-blocks"||i.startsWith(".three-blocks/"))return;let s=b.posix.extname(i).toLowerCase(),a=new Set([i]);if(s.length===0||!je.has(s)){for(let c of Te)a.add(`${i}${c}`);for(let c of Te)a.add(`${i}/index${c}`);}else if([".js",".mjs",".cjs",".jsx"].includes(s)){let c=i.slice(0,-s.length);for(let f of [".ts",".tsx",".mts",".cts"])a.add(`${c}${f}`);}return [...a].find(c=>r.has(c))}o(fr,"resolveProjectImport");function pr(e,t){let r=Ce(t,false);return rr.test(e)||nr.test(r)||ir.test(r)}o(pr,"isShaderRoot");async function Ie(e,t){let r=await realpath(e);if(t!==void 0){let d={},p=0;for(let g of t){let u=await B(r,b.join(r,g),$.semanticInput,"Declared shader semantic input");if(p+=u.data.byteLength,p>$.semanticTotal)throw new Error("Declared shader semantic inputs exceed the total inspection size limit.");d[g]=I(u.data);}return d}let n=new Map,i=b.join(r,"src");if(await C(i))for(let d of await Ve(r,i,p=>je.has(b.extname(p).toLowerCase()))){let p=await B(r,d,$.semanticInput,"Shader semantic input");n.set(lt(r,d),p.data);}for(let d of await readdir(r,{withFileTypes:true})){if(!d.isFile()||!xe.test(d.name)&&!je.has(b.extname(d.name).toLowerCase()))continue;let p=await B(r,b.join(r,d.name),$.semanticInput,xe.test(d.name)?"Shader configuration input":"Shader semantic input");n.set(d.name,p.data);}if(n.size>$e)throw new Error(`Shader input discovery exceeds the ${$e}-file limit.`);let s=new Set,a=new Map;for(let[d,p]of n){if(!d.includes("/")&&xe.test(d)&&s.add(d),!d.startsWith("src/"))continue;let g=Ae(p,d);a.set(d,g),pr(d,g)&&s.add(d);}if(s.size===0)throw new Error("No shader registration or scene source root was found.");let c=new Set,f=[...s].sort();for(;f.length>0;){let d=f.shift();if(d===void 0||c.has(d))continue;let p=n.get(d);if(p===void 0)continue;c.add(d);let g=a.get(d)??Ae(p,d);for(let u of ur(g)){let R=fr(d,u,n);R!==void 0&&!c.has(R)&&f.push(R);}f.sort();}let m=0,h={};for(let d of [...c].sort()){let p=n.get(d);if(p===void 0)throw new Error(`Shader input ${JSON.stringify(d)} disappeared during inspection.`);if(m+=p.byteLength,m>$.semanticTotal)throw new Error("Semantic shader inputs exceed the total inspection size limit.");h[d]=I(p);}return h}o(Ie,"snapshotShaderInputs");function Me(e){if(typeof e=="string")return e;if(l(e))return Me(e.import)??Me(e.default)}o(Me,"conditionalImportTarget");async function ct(e,t){let r=e;for(;;){let n=b.join(r,"node_modules",...t.split("/"),"package.json");if(await C(n)){let s=await ye(n,$.packageJson,`${t} package.json`),a=JSON.parse(s.data.toString("utf8"));if(!l(a)||a.name!==t||typeof a.version!="string"||!dr.test(a.version))throw new Error(`Installed ${t} package metadata is invalid.`);return {root:b.dirname(s.path),manifest:a}}let i=b.dirname(r);if(i===r)break;r=i;}throw new Error(`Cannot verify the installed ${t} package.`)}o(ct,"findInstalledPackage");async function mr(e,t){if(!l(t.exports))throw new Error("Installed three-blocks package has no public exports map.");let r=Me(t.exports[cr]);if(r===void 0||!r.startsWith("./"))throw new Error("Installed three-blocks shader export has no import target.");let n=await realpath(e),i=[b.resolve(n,r)],s=new Map,a=0;for(;i.length>0;){let f=i.shift();if(f===void 0)break;let m=await ye(f,$.semanticInput,"Three Blocks shader runtime module");if(!v(n,m.path)||m.path===n)throw new Error("Three Blocks shader runtime closure escapes its package.");let h=lt(n,m.path);if(s.has(h))continue;if(a+=m.data.byteLength,a>$.semanticTotal)throw new Error("Three Blocks shader runtime closure exceeds the inspection limit.");s.set(h,I(m.data));let d=Ae(m.data,h);for(let p of lr(d)){let g=ft(p);if(!g.startsWith("./")&&!g.startsWith("../"))continue;let u=b.resolve(b.dirname(m.path),g);if(!v(n,u))throw new Error("Three Blocks shader runtime import escapes its package.");i.push(u);}if(i.sort(),s.size+i.length>$e)throw new Error("Three Blocks shader runtime closure exceeds the file limit.")}let c=[...s].sort((f,m)=>f[0].localeCompare(m[0])).map(([f,m])=>`${f}\0${m}`).join(`
|
|
19
|
+
`);return I(c)}o(mr,"shaderRuntimeClosure");async function _e(e){let[t,r]=await Promise.all([ct(e,"three"),ct(e,"three-blocks")]);return {three:String(t.manifest.version),threeBlocks:String(r.manifest.version),threeBlocksShaderClosure:await mr(r.root,r.manifest)}}o(_e,"readInstalledShaderRuntime");var Z;async function gr(){Z===void 0&&(Z=(async()=>{let t=createRequire(b.join(process.cwd(),"package.json")).resolve("@three-blocks/devtools/browser/shader-capture"),r=b.resolve(b.dirname(t),"../..");return (await B(r,t,$.metadata,"Shader capture browser runtime")).data.toString("utf8")})());let e=Z;try{return await e}catch(t){throw Z===e&&(Z=void 0),t}}o(gr,"loadShaderCaptureRuntimeSource");var pt=4096,Sr=createRequire(import.meta.url),mt,E=new Proxy({},{get(e,t){return mt??=Sr("typescript"),Reflect.get(mt,t)}});function H(e){let t=e;for(;E.isParenthesizedExpression(t)||E.isAsExpression(t)||E.isSatisfiesExpression(t)||E.isNonNullExpression(t);)t=t.expression;return t}o(H,"unwrap");function wr(e){if(E.isIdentifier(e)||E.isStringLiteral(e)||E.isNumericLiteral(e))return e.text}o(wr,"propertyName");function Q(e,t){let r=new Map;for(let n of e.properties){if(!E.isPropertyAssignment(n))throw new Error(`${t} may contain only static property assignments.`);let i=wr(n.name);if(i===void 0||r.has(i))throw new Error(`${t} contains a computed or duplicate property.`);r.set(i,n.initializer);}return r}o(Q,"properties");function ee(e,t){if(e===void 0)throw new Error(`${t} is missing.`);let r=H(e);if(!E.isObjectLiteralExpression(r))throw new Error(`${t} must be a static object literal.`);return r}o(ee,"objectLiteral");function te(e,t){if(e===void 0)throw new Error(`${t} is missing.`);let r=H(e);if(!E.isStringLiteral(r)&&!E.isNoSubstitutionTemplateLiteral(r))throw new Error(`${t} must be a string literal.`);return r.text}o(te,"stringLiteral");function he(e,t){if(e===void 0)throw new Error(`${t} is missing.`);let r=H(e);if(!E.isNumericLiteral(r))throw new Error(`${t} must be a numeric literal.`);return Number(r.text)}o(he,"numericLiteral");function ht(e,t){if(e===void 0)throw new Error(`${t} is missing.`);let r=H(e);if(!E.isArrayLiteralExpression(r))throw new Error(`${t} must be a static array literal.`);return r.elements}o(ht,"arrayLiteral");function br(e,t){if(e===void 0)throw new Error(`${t} is missing.`);let r=H(e);if(r.kind===E.SyntaxKind.NullKeyword)return null;if(!E.isNumericLiteral(r))throw new Error(`${t} must be null or a numeric literal.`);return Number(r.text)}o(br,"numericOrNullLiteral");function Er(e){return e.parseDiagnostics??[]}o(Er,"parseDiagnostics");function gt(e,t,r,n){let i=E.createSourceFile(t,e,E.ScriptTarget.Latest,true,E.ScriptKind.TS),s=Er(i);if(s.length>0)throw new Error(`Shader manifest is not valid TypeScript: ${E.flattenDiagnosticMessageText(s[0]?.messageText??"parse error"," ")}`);let a=i.statements.filter(E.isExportAssignment).filter(y=>!y.isExportEquals);if(a.length!==1)throw new Error("Shader manifest must contain exactly one default export.");let c=Q(ee(a[0]?.expression,"Shader manifest default export"),"Shader manifest"),f=c.get("version");if(f===void 0||!E.isNumericLiteral(H(f))||Number(H(f).getText(i))!==3)throw new Error("Shader manifest version must be the numeric literal 3.");if(te(c.get("scene"),"Shader manifest scene")!==r)throw new Error(`Shader manifest scene does not match "${r}".`);let m=c.get("runtime"),d=(n?.compatibility??(m===void 0?"":te(Q(ee(m,"Shader manifest runtime"),"Shader manifest runtime").get("id"),"Shader manifest runtime id"))).startsWith("three-webgl-");if(n){if(te(c.get("three"),"Shader manifest Three.js version")!==n.three||te(c.get("threeBlocks"),"Shader manifest Three Blocks version")!==n.threeBlocks)throw new Error("Shader manifest runtime versions do not match its receipt.");let y=Q(ee(c.get("runtime"),"Shader manifest runtime"),"Shader manifest runtime");if(te(y.get("id"),"Shader manifest runtime id")!==n.compatibility||he(y.get("address"),"Shader manifest address schema")!==n.address||he(y.get("recipe"),"Shader manifest recipe schema")!==n.recipe||he(y.get("hydration"),"Shader manifest hydration schema")!==n.hydration)throw new Error("Shader manifest runtime compatibility schemas do not match its receipt.")}let p=Q(ee(c.get("entries"),"Shader manifest entries"),"Shader manifest entries");if(p.size===0&&!d||p.size>pt)throw new Error(`Shader manifest must contain ${d?"0":"1"}...${pt} entries.`);let g=ht(c.get("modules"),"Shader manifest modules").map((y,k)=>{let x=H(y);if(!E.isStringLiteral(x)&&!E.isNoSubstitutionTemplateLiteral(x))throw new Error(`Shader manifest module ${k} must be a shader string literal.`);if(x.text.length===0)throw new Error(`Shader manifest module ${k} is empty.`);return x.text}),u=ht(c.get("states"),"Shader manifest states").map((y,k)=>{let x=Q(ee(y,`Shader manifest state ${k}`),`Shader manifest state ${k}`),A=o((V,T)=>{let S=br(x.get(V),`Shader manifest state ${k} ${V}`);if(S===null)return false;let N=g[S];if(N===void 0||!d&&!N.includes(T))throw new Error(`Shader manifest state ${k} ${V} does not reference a ${T} module.`);return true},"moduleAt"),O=A("vertex","@vertex"),_=A("fragment","@fragment"),F=A("compute","@compute");if(F&&(O||_))throw new Error(`Shader manifest state ${k} mixes render and compute stages.`);if(!F&&!O&&!_)throw new Error(`Shader manifest state ${k} contains no shader stage.`);return {vertex:O,fragment:_,compute:F}}),R={render:0,vertex:0,fragment:0,compute:0};for(let[y,k]of p){if(y.length===0||/[\u0000-\u001f\u007f]/.test(y))throw new Error("Shader manifest contains an invalid entry key.");let x=he(k,`Shader manifest entry "${y}"`),A=u[x];if(A===void 0)throw new Error(`Shader manifest entry "${y}" references an absent state.`);(A.vertex||A.fragment)&&(R.render+=1),A.vertex&&(R.vertex+=1),A.fragment&&(R.fragment+=1),A.compute&&(R.compute+=1);}return R}o(gt,"inspectPrecompiledManifest");function kr(e,t){return e.render===t.render&&e.vertex===t.vertex&&e.fragment===t.fragment&&e.compute===t.compute}o(kr,"sameCoverage");function Rr(e){let t=e.some(n=>n.state==="invalid")?"invalid":e.some(n=>n.state==="missing")?"missing":e.some(n=>n.state==="stale")?"stale":"fresh",r=e.filter(n=>n.state===t);return {state:t,reason:t==="fresh"?`${e.length} configured shader scene${e.length===1?" is":"s are"} fresh.`:r.map(n=>`${n.scene} (${n.backend}): ${n.reason}`).join("; ")}}o(Rr,"classifyMatrix");function xr(e,t,r){let n=e.tool;if(!n)return "Shader receipt has no public tool compatibility metadata.";if((n.compatibilities?.[r]??n.compatibility)!==t)return "Shader receipt targets a different runtime compatibility contract.";if(n.transform!==me)return "Shader receipt uses a different provider transform version.";if(n.address!==SHADER_ADDRESS_SCHEMA_VERSION||n.recipe!==SHADER_RECIPE_SCHEMA_VERSION||n.hydration!==SHADER_HYDRATION_SCHEMA_VERSION)return "Shader receipt uses incompatible address, recipe, or hydration schemas."}o(xr,"exactToolCompatibility");function Tr(e,t){let r=Object.keys(t).filter(s=>Object.hasOwn(e,s)&&e[s]!==t[s]),n=Object.keys(t).filter(s=>!Object.hasOwn(e,s)),i=Object.keys(e).filter(s=>!Object.hasOwn(t,s));return {...r.length>0?{changedInputs:r}:{},...n.length>0?{addedInputs:n}:{},...i.length>0?{removedInputs:i}:{}}}o(Tr,"inputChanges");async function jr(e=process.cwd(),t,r){let n=await Xe(e),i=await ke(n),s=qe(r??i.backend),a=i.scenes.flatMap(m=>J(m,s).map(h=>({scene:m,backend:h,key:K(m.key,h)}))),c=b.join(n,Ee),f=o(()=>({schemaVersion:1,root:n,state:"missing",reason:`${Ee}/meta.json is absent.`,scenes:a.map(({scene:m,backend:h})=>({scene:m.key,backend:h,state:"missing",reason:"No committed shader receipt."}))}),"missing");if(!await C(c)||!await C(b.join(c,"meta.json")))return f();try{let m=await U(n,c,"Shader artifact directory"),h=await B(m,b.join(m,"meta.json"),$.receipt,"Shader receipt"),d=le(JSON.parse(h.data.toString("utf8"))),p=await dt(m,h.data),g=t??await _e(n),u=new Set(i.scenes.flatMap(T=>J(T,["webgpu","webgl"]).map(S=>K(T.key,S)))),y=Object.keys(d.scenes).filter(T=>!u.has(T));if(y.length>0)throw new Error(`Shader receipt contains unconfigured scenes: ${y.join(", ")}.`);let k=d.runtime.three!==g.three,x=d.runtime.threeBlocksShaderClosure!==g.threeBlocksShaderClosure,A=d.tool?.version!==X,O=b.join(n,i.publicDir??"public"),_=[];for(let{scene:T,backend:S,key:N}of a){let j=d.scenes[N];if(!j){_.push({scene:T.key,backend:S,state:"missing",reason:"Scene/backend is absent from the complete receipt matrix."});continue}let re=Y(g.three,S),Pe=xr(d,re,S);if(Pe)throw new Error(`${N}: ${Pe}`);let ne=await B(m,b.join(m,j.artifact),$.manifest,"Shader manifest");if(I(ne.data)!==j.artifactHash)throw new Error(`Shader artifact checksum differs for scene "${T.key}".`);if(j.asset!==void 0&&j.assetHash!==void 0){let Et=await B(O,b.join(O,j.asset),$.manifest,"Static shader manifest");if(I(Et.data)!==j.assetHash)throw new Error(`Static shader manifest checksum differs for scene "${T.key}".`)}if(j.bytes!==void 0&&j.bytes!==ne.data.byteLength)throw new Error(`Shader artifact byte count differs for scene "${T.key}".`);let ie=gt(ne.data.toString("utf8"),ne.path,T.key,{three:d.runtime.three,threeBlocks:d.runtime.threeBlocks,compatibility:re,address:SHADER_ADDRESS_SCHEMA_VERSION,recipe:SHADER_RECIPE_SCHEMA_VERSION,hydration:SHADER_HYDRATION_SCHEMA_VERSION});if(!kr(ie,j.coverage))throw new Error(`Shader coverage differs for scene "${T.key}".`);if(S==="webgpu"&&!i.allowLiveBuilds&&j.skipped&&j.skipped.render+j.skipped.compute>0)throw new Error(`Scene "${T.key}" contains skipped live builds but allowLiveBuilds is false.`);let bt=await Ie(n,T.inputs),se=Tr(j.inputs,bt),oe=(se.changedInputs?.length??0)+(se.addedInputs?.length??0)+(se.removedInputs?.length??0),Oe=k||x||A||oe>0,Ne=p?.scenes[N],ge=Ne===void 0||p===void 0?void 0:{...Ne,schemaVersion:p.schemaVersion,measuredAt:p.measuredAt,source:p.source,...p.source==="committed-capture"?{adapter:p.adapter,platform:p.platform}:{}};_.push({scene:T.key,backend:S,state:Oe?"stale":"fresh",reason:k?"Installed Three.js version differs from the receipt.":x?"Installed three-blocks/shaders runtime closure differs from the receipt.":A?`Receipt was generated by @three-blocks/devtools ${d.tool?.version??"unknown"}.`:oe>0?`${oe} semantic shader input${oe===1?"":"s"} changed.`:"Manifest, runtime, schemas, transform, and semantic inputs match.",coverage:ie,...!Oe&&ge!==void 0&&ge.builds===ie.render+ie.compute?{timing:ge}:{},...se});}let F=Rr(_),V=F.state==="fresh"&&p!==void 0&&_.every(T=>T.timing!==void 0)?p:void 0;return {schemaVersion:1,root:n,...F,scenes:_,runtime:g,receipt:d,...V===void 0?{}:{timing:V}}}catch(m){let h=m instanceof Error?m.message:String(m);return {schemaVersion:1,root:n,state:"invalid",reason:h,scenes:a.map(({scene:d,backend:p})=>({scene:d.key,backend:p,state:"invalid",reason:h}))}}}o(jr,"inspectShaderMatrix");export{me as SHADER_PROVIDER_TRANSFORM_VERSION,jr as inspectShaderMatrix,gr as loadShaderCaptureRuntimeSource,ke as loadShaderToolConfig,_e as readInstalledShaderRuntime,Ie as snapshotShaderInputs,q as stableStringify,Yt as validateShaderCapture,er as writeShaderArtifacts};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {e}from'./chunk-
|
|
2
|
+
import {e}from'./chunk-NQIAU3XU.js';import'./chunk-FKZT7XLM.js';import'./chunk-QJFPNM6W.js';import'./chunk-ZT6T2W4B.js';import {i}from'./chunk-NPLE7PPF.js';import'./chunk-65VEJRRT.js';import'./chunk-5L2VS3BN.js';import {a}from'./chunk-HOZDD6PW.js';import {watch}from'fs';import v from'path';var o=class{static{a(this,"ShaderWatchQueue");}#s;#r;#a;#e;#t;#i=false;#n=false;constructor(r){if(this.#s=r.capture,this.#r=r.debounceMs??200,this.#a=r.onError??(()=>{}),!Number.isSafeInteger(this.#r)||this.#r<0||this.#r>6e4)throw new Error("Shader watch debounce must be an integer in 0...60000ms.")}notify(){this.#n||(this.#i=true,!this.#t&&(this.#e&&clearTimeout(this.#e),this.#e=setTimeout(()=>{this.#e=void 0,this.#o();},this.#r)));}#o(){this.#n||this.#t||!this.#i||(this.#i=false,this.#t=this.#s().catch(r=>{this.#a(r instanceof Error?r:new Error(String(r)));}).finally(()=>{this.#t=void 0,this.#i&&!this.#n&&this.notify();}));}async close(){this.#n=true,this.#i=false,this.#e&&clearTimeout(this.#e),this.#e=void 0,await this.#t;}};function y(e){let r=e.split(v.sep).join("/");return r===""||r.startsWith("node_modules/")||r.startsWith(".git/")||r.startsWith("dist/")||r===".three-blocks"||r.startsWith(".three-blocks/")}a(y,"ignored");async function W(e$1={}){let r=e$1.root??await i(e$1.start),d,l=new Promise(t=>{d=t;}),n=new o({...e$1.debounceMs!==void 0?{debounceMs:e$1.debounceMs}:{},...e$1.onError?{onError:e$1.onError}:{},capture:a(async()=>{let t=await e({root:r,...e$1.config?{config:e$1.config}:{},...e$1.driver?{driver:e$1.driver}:{},...e$1.driverKind?{driverKind:e$1.driverKind}:{},...e$1.serve?{serve:e$1.serve}:{},...e$1.url?{url:e$1.url}:{},...e$1.headed!==void 0?{headed:e$1.headed}:{},...e$1.attempts!==void 0?{attempts:e$1.attempts}:{}});e$1.onResult?.(t);},"capture")}),s,u=false,a$1=a(async()=>{u||(u=true,s?.close(),await n.close(),d?.());},"close");return s=watch(r,{recursive:true},(t,f)=>{y(f??"")||n.notify();}),s.on("error",t=>e$1.onError?.(t)),e$1.signal&&(e$1.signal.aborted?await a$1():e$1.signal.addEventListener("abort",()=>{a$1();},{once:true})),e$1.initial!==false&&n.notify(),{root:r,done:l,close:a$1}}a(W,"watchShaders");export{o as ShaderWatchQueue,W as watchShaders};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
export{e as captureShaders,d as inspectShaderMatrix,f as testShaders}from'./chunk-NQIAU3XU.js';import'./chunk-FKZT7XLM.js';import'./chunk-QJFPNM6W.js';import'./chunk-ZT6T2W4B.js';import'./chunk-NPLE7PPF.js';import'./chunk-65VEJRRT.js';import'./chunk-5L2VS3BN.js';import'./chunk-HOZDD6PW.js';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
export{b as RUNTIME_STATUS_RECEIPT_MAX_BYTES,a as RUNTIME_STATUS_RECEIPT_PATH,c as RUNTIME_STATUS_RECOVERY,e as findProjectRoot,i as formatShaderMatrixStatus,j as formatStatus,k as formatThreeBlocksStatus,f as inspectProject,g as inspectThreeBlocksStatus,d as parseRuntimeStatusReceipt,h as threeBlocksStatusIsFresh}from'./chunk-
|
|
2
|
+
export{b as RUNTIME_STATUS_RECEIPT_MAX_BYTES,a as RUNTIME_STATUS_RECEIPT_PATH,c as RUNTIME_STATUS_RECOVERY,e as findProjectRoot,i as formatShaderMatrixStatus,j as formatStatus,k as formatThreeBlocksStatus,f as inspectProject,g as inspectThreeBlocksStatus,d as parseRuntimeStatusReceipt,h as threeBlocksStatusIsFresh}from'./chunk-L2CZ7RSV.js';import'./chunk-76WRV5MZ.js';import'./chunk-JHBQB7WC.js';export{c as readInstalledShaderRuntime,b as snapshotShaderInputs}from'./chunk-NQIAU3XU.js';import'./chunk-FKZT7XLM.js';import'./chunk-QJFPNM6W.js';import'./chunk-ZT6T2W4B.js';import'./chunk-NPLE7PPF.js';import'./chunk-65VEJRRT.js';import'./chunk-5L2VS3BN.js';import'./chunk-HOZDD6PW.js';
|
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-
|
|
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-AIAYEDXX.js';import'./chunk-3CKEE22B.js';import'./chunk-EI7MMDWY.js';
|
package/dist/webpack-loader.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import {e}from'./chunk-
|
|
1
|
+
import {e}from'./chunk-AIAYEDXX.js';import'./chunk-3CKEE22B.js';import {a}from'./chunk-EI7MMDWY.js';function o(e$1){return e(e$1,this.resourcePath,this.getOptions?.()??{})?.code??e$1}a(o,"threeBlocksShaderLoader");export{o as default};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@three-blocks/devtools",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0-alpha.282.g3f938d990c02",
|
|
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",
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
"@types/three": "0.185.0",
|
|
80
80
|
"create-vite": "9.1.1",
|
|
81
81
|
"playwright": "^1.61.1",
|
|
82
|
-
"three-blocks": "0.
|
|
82
|
+
"three-blocks": "0.4.0-alpha.282.g3f938d990c02",
|
|
83
83
|
"tsup": "^8.0.0",
|
|
84
84
|
"typescript": "^5.9.3",
|
|
85
85
|
"vite": "^7.2.2",
|
|
@@ -90,8 +90,8 @@
|
|
|
90
90
|
},
|
|
91
91
|
"peerDependencies": {
|
|
92
92
|
"playwright": "^1.61.1",
|
|
93
|
-
"three": ">=0.185.0
|
|
94
|
-
"three-blocks": "0.
|
|
93
|
+
"three": ">=0.185.0",
|
|
94
|
+
"three-blocks": "0.4.0-alpha.282.g3f938d990c02",
|
|
95
95
|
"typescript": ">=5.9.3 <7.0.0",
|
|
96
96
|
"vite": ">=7.2.2 <9.0.0"
|
|
97
97
|
},
|
package/dist/chunk-V34C7NIM.js
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import {d,a as a$1,X,z,Y,B,U,m,l,h,g,S}from'./chunk-GA7PGW2R.js';import {a}from'./chunk-EI7MMDWY.js';import x from'process';import {createServer}from'http';import {createRequire}from'module';import {mkdtemp,rm,lstat,realpath}from'fs/promises';import A from'path';import {tmpdir}from'os';import {pathToFileURL}from'url';var Le=Object.freeze([{id:"three-inspector-invalid-json",pattern:/is not valid JSON/iu},{id:"chromium-webgpu-experimental",pattern:/WebGPU is experimental/iu}]);function it(n){return Le.some(e=>e.pattern.test(n))}a(it,"isDocumentedBrowserNoise");function me(n=x.env,e=x.platform){let t=n.THREE_BLOCKS_WEBGPU_BROWSER_ARGS?.split(/\s+/u).filter(Boolean);if(t&&t.length>0)return t;let r=["--enable-unsafe-webgpu"];return e==="darwin"&&r.push("--enable-gpu","--use-angle=metal"),e==="linux"&&r.push("--enable-features=Vulkan","--disable-vulkan-surface","--ignore-gpu-blocklist","--disable-gpu-driver-bug-workarounds","--disable-gpu-watchdog"),r}a(me,"webgpuBrowserArgs");function fe(n=x.env){let e=n.THREE_BLOCKS_WEBGL_BROWSER_ARGS?.split(/\s+/u).filter(Boolean);return e&&e.length>0?e:["--use-angle=swiftshader","--enable-unsafe-swiftshader","--ignore-gpu-blocklist"]}a(fe,"webglBrowserArgs");function pe(n=false,e=x.env){return n!==true&&e.THREE_BLOCKS_SOFTWARE_WEBGPU!=="1"}a(pe,"webgpuBrowserHeadless");var Z="three-blocks.shader-capture.runtime.v1";var Re="/__three-blocks/shaders/capture",K="/__three-blocks/shaders/telemetry",Te="/__three-blocks/shaders/runtime.js",ke="/__three-blocks/shaders/bootstrap.js",Ee="/__three-blocks/shaders/bridge.js",Pe=d.manifest*2,re=/^[a-z0-9][a-z0-9_-]{0,63}$/u,Ce=64,Be=2e3,We=[/is not valid JSON/iu,/WebGPU is experimental/iu];async function Ve(){try{return (await import('playwright')).chromium}catch(n){throw new Error('Shader browser work requires the optional "playwright" package. Install it in the project and run `npx playwright install chromium`.',{cause:n})}}a(Ve,"loadChromium");async function Je(n){let e;try{e=createRequire(A.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(Je,"loadProjectCreateServer");var ne=class{static{a(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,o)=>{let s=setTimeout(()=>{this.#e.delete(e),o(new Error(`Shader capture "${e}" timed out after ${t}ms.`));},t);this.#e.set(e,{resolve:a,reject:o,timer:s});})}receive(e){if(!a$1(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>=Ce)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 Ke(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(Ke,"waitForShaderCaptureAcrossNavigation");var ae=class{static{a(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$1(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>=Ce)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);}},qe=a(async(n,e,t,r,a)=>{let o=0;for(;n.__threeBlocksParityUsesAnimationLoop!==true&&o<e;)await r(),o+=1;if(n.__threeBlocksParityUsesAnimationLoop===true){let s=Number(n.__threeBlocksParityCompletedFrame||0),i=Number(t),d=Number.isSafeInteger(i)&&i>=s?i:s+e;for(n.__threeBlocksParityTargetFrame=d;Number(n.__threeBlocksParityCompletedFrame||0)<d;)await r();}return await a(),Number(n.__threeBlocksParityCompletedFrame||0)},"settleShaderParityFrames");function se(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 = ${qe.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(se,"publicBridgeScript");function _e(n,e,t,r,a=false){let o=new URL(n.url??"/","http://three-blocks.invalid"),s=o.pathname;if(a&&n.method==="GET"&&/^\/three-blocks\/shaders\/[a-z0-9][a-z0-9_-]{0,63}\.(?:webgpu|webgl)\.json$/u.test(s))return e.statusCode=204,e.end(),true;if(s===K&&n.method==="GET"){let h=o.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=s===Re,d=s===K;if(!i&&!d)return false;if(n.method!=="POST")return e.statusCode=405,e.end("POST required"),true;let c=[],w=0,f=false;return n.on("data",h=>{w+=h.byteLength,w>Pe?f=true:c.push(h);}),n.on("end",()=>{if(f){e.statusCode=413,e.end("capture payload too large");return}try{let h=JSON.parse(Buffer.concat(c).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(_e,"handleCaptureEndpoint");function ze(n,e,t,r,a){return {name:"three-blocks:shader-capture-endpoint",transformIndexHtml(){return [{tag:"script",children:se(r,a),injectTo:"head-prepend"}]},configureServer(o){o.middlewares.use((s,i,d)=>{let w=new URL(s.url??"/","http://three-blocks.invalid").searchParams.get("captureId");w!==null&&e.markFirstRequest(w),!_e(s,i,n,e,t)&&d();});}}}a(ze,"captureEndpointPlugin");function ge(n,e,t){let r=new URL(e.url,n);for(let[a,o]of Object.entries(t))r.searchParams.set(a,o);return r.href}a(ge,"browserUrl");function Ye(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(Ye,"publishedBrowserUrl");function ye(n){return We.some(e=>e.test(n))}a(ye,"knownNoise");async function M(n){let e;try{await Promise.race([n(),new Promise(t=>{e=setTimeout(t,Be);})]);}catch{}finally{e&&clearTimeout(e);}}a(M,"closeBrowserResource");async function J(n){let e;try{return await Promise.race([n().catch(()=>null),new Promise(t=>{e=setTimeout(()=>t(null),Be);})])}finally{e!==void 0&&clearTimeout(e);}}a(J,"readPageDiagnostic");function ee(n){let e=a(()=>{},"resolveFirst"),t=new Promise(s=>{e=s;}),r={console:[],page:[],first:t},a$1=false,o=a(s=>{a$1||(a$1=true,e(new Error(s)));},"report");return n.on("console",s=>{let i=s.type()==="warning"&&/\[three-blocks\/shaders\].*(?:has no entry|manifest miss|hydration)/iu.test(s.text());if(s.type()!=="error"&&!i||ye(s.text()))return;let d=s.location().url,c=d.length>0?`${s.text()} (${d})`:s.text();r.console.push(c),o(`Browser console ${i?"warning":"error"}: ${c}`);}),n.on("pageerror",s=>{if(ye(s.message))return;let i=s.stack||s.message;r.page.push(i),o(`Browser page error: ${i}`);}),n.on("crash",()=>o("Browser page crashed before shader capture completed.")),n.on("close",()=>o("Browser page closed before shader capture completed.")),r}a(ee,"collectErrors");function L(n,e,t=false){return typeof n[e]=="boolean"?n[e]:t}a(L,"booleanField");function Xe(n){if(!a$1(n))throw new Error("Browser shader stats are unavailable.");let e=a((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(Xe,"parseStats");function W(n,e,t,r,a){if(!a$1(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 o=n.readiness;if(!a$1(o))throw new Error("The shader bridge readiness snapshot is invalid.");let s={workerReady:L(o,"workerReady"),assetsReady:L(o,"assetsReady"),textReady:e.requiresText?L(o,"textReady"):true,compileEnd:L(o,"compileEnd"),firstFrame:L(o,"firstFrame",t)};if(!s.workerReady||!s.assetsReady||!s.textReady||!s.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.`);Y(r);let c=Array.isArray(n.demands)?n.demands.filter(a$1).slice(0,64):void 0;return {compatibility:a,transform:d,readiness:s,stats:Xe(n.stats),...c===void 0?{}:{demands:c}}}a(W,"parseBridge");async function V(n,e){return n.evaluate(t=>{let r=globalThis;if(!t)return r.__threeBlocksShaderTools??null;let a=r.__threeBlocks,o=r.__threeBlocksTslStats;if(!a||typeof a!="object")return null;let s=a;return {readiness:{workerReady:s.workerReady===true,assetsReady:s.loadEnd===true||s.assetsReady===true,textReady:s.textReady===true,compileEnd:s.compileEnd===true,firstFrame:true},stats:o}},e)}a(V,"readBridge");async function xe(n,e){let t=await J(()=>n.evaluate(r=>{let a$1=globalThis,o=a(i=>{let d=a$1;for(let c of i.split(".")){if(d===null||typeof d!="object"&&typeof d!="function")return;d=Reflect.get(d,c);}return d},"resolveGlobal"),s=null;if(r!==null)try{s=JSON.stringify(o(`${r}Diagnostics`))??null;}catch{s=null;}return JSON.stringify({parityCompletedFrame:Number(a$1.__threeBlocksParityCompletedFrame??0),diagnostics:s})},e??null));return t===null?{alive:false,signature:""}:{alive:true,signature:t}}a(xe,"probePageProgress");async function F(n,e,t,r){let a$1=n.evaluate(async c=>{let f=globalThis.__threeBlocksShaderTools;if(f&&typeof f=="object"){let y=Reflect.get(f,"settle");if(typeof y=="function"){let u=await y(c.frames,c.targetFrame);return typeof u=="number"&&Number.isSafeInteger(u)?u:0}}if(!c.legacy||!c.modulePath)throw new Error("The public shader bridge does not provide deterministic settle().");let h=await import(c.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=c.frames,S.recording=true,await new Promise((y,u)=>{let p=Date.now(),m=a(()=>{if(S.recording===false)return y();if(Date.now()-p>c.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}),o=j(e),s=false,i,d=(async()=>{let c=Date.now(),w=c,f="";for(;;){let h=o-(Date.now()-c);if(h<=0)throw new Error(`Shader parity settle timed out after ${o}ms.`);let S=e.timeoutMs-(Date.now()-w);if(S<=0){let y=await xe(n,e.readiness.global);if(s)throw new Error("Shader parity settle already resolved.");if(y.alive&&y.signature===f)throw new Error(`Shader parity settle timed out after ${e.timeoutMs}ms without progress (hard cap ${o}ms).`);f=y.signature,w=Date.now();continue}if(await new Promise(y=>{i=setTimeout(y,Math.min(S,h,2500));}),s)throw new Error("Shader parity settle already resolved.")}})();try{return await Promise.race([a$1,d])}finally{s=true,i!==void 0&&clearTimeout(i),d.catch(()=>{});}}a(F,"settlePage");async function Se(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 o=a;for(let d of r.global.split(".")){if((typeof o!="object"||o===null)&&typeof o!="function")return false;o=Reflect.get(o,d);}if(o===true)return true;if(typeof o!="object"||o===null||typeof Reflect.get(o,"then")!="function")return false;let s=a.__threeBlocksReadinessState,i=s instanceof Map?s:new Map;return s instanceof Map||(a.__threeBlocksReadinessState=i),i.has(o)||(i.set(o,false),Promise.resolve(o).then(()=>i.set(o,true),()=>i.set(o,false))),i.get(o)===true},e.readiness,{timeout:j(e)}),t.first.then(r=>Promise.reject(r))]);}a(Se,"waitForConfiguredReadiness");async function be(n){let e=n.locator("canvas"),r=(await e.evaluateAll(a=>a.map((o,s)=>{let i=o.getBoundingClientRect();return {index:s,area:Math.max(0,i.width)*Math.max(0,i.height)}}))).sort((a,o)=>o.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(be,"primaryCanvasScreenshot");async function te(n,e,t,r,a,o,s){let i=q(r,a,o),d=await U(),c=`(() => {
|
|
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
|
-
${c}`}),await n.addInitScript({content:se(s,i)}),await n.route("**/*",async w=>{let f=w.request(),h=new URL(f.url()),S=h.pathname;if(f.method()==="GET"&&r!=="precompiled"&&/^\/three-blocks\/shaders\/[a-z0-9][a-z0-9_-]{0,63}\.(?:webgpu|webgl)\.json$/u.test(S)){await w.fulfill({status:204});return}if(S===K&&f.method()==="GET"){let p=t.read(h.searchParams.get("scene")??"");await w.fulfill(p===void 0?{status:204}:{status:200,contentType:"application/json",body:JSON.stringify(p)});return}let y=S===Re,u=S===K;if((y||u)&&f.method()==="POST"){let p=f.postDataBuffer()??Buffer.alloc(0);if(p.byteLength>Pe){await w.fulfill({status:413,body:"capture payload too large"});return}try{let m=JSON.parse(p.toString("utf8"));u?t.receive(m):e.receive(m),await w.fulfill({status:204});}catch(m){await w.fulfill({status:400,body:m instanceof Error?m.message:String(m)});}return}await w.continue();});}a(te,"configureAttachedContext");var Qe=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 Ze(n){let e=[`<script src="${Ee}"></script>`,`<script type="module" src="${ke}"></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(Ze,"injectStaticShaderCaptureHtml");function et(n,e,t){let r=q(n,e,t);return [`import { configureThreeBlocksShaderCapture } from ${JSON.stringify(Te)};`,`configureThreeBlocksShaderCapture( ${JSON.stringify(r).replaceAll("<","\\u003c")} );`].join(`
|
|
77
|
-
`)}a(et,"staticCaptureBootstrap");var tt=5e3;function j(n){return Math.max(n.maxTimeoutMs??n.timeoutMs,n.timeoutMs)}a(j,"configuredHardCapMs");function q(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,j(e)-tt)}:{},readiness:e.readiness,transform:B}}a(q,"shaderCaptureConfiguration");async function rt(n,e){let t=await m(n,e,s=>/\.(?:c|m)?js$/u.test(s),16384),r=false,a=false,o;for(let s of t){let i=(await l(n,s,d.texture,"Static application JavaScript")).data.toString("utf8");if(i.includes("nodeBuilderStateProvider")&&(r=true),i.includes("three-blocks.shader-capture.runtime.v1")&&(a=true,o??=s),r&&a)break}if(!r||!a)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,...o===void 0?{}:{id:o}}}a(rt,"inspectStaticCaptureTransform");async function nt(n,e){let t;try{t=decodeURIComponent(e);}catch{return}if(t.includes("\0"))return;let r=t.replace(/^\/+/u,""),a=A.resolve(n,r.length===0?"index.html":r);if(!h(n,a)||a===n||(await g(a)&&(await lstat(a)).isDirectory()&&(a=A.join(a,"index.html")),!await g(a)&&A.extname(a).length===0&&(a=A.join(n,"index.html")),!await g(a)))return;let o=await l(n,a,d.texture,"Static application asset");return {data:o.data,file:o.path}}a(nt,"staticRequestFile");async function at(n,e,t,r,a,o){let s=await realpath(n.root),i=await realpath(A.resolve(s,n.serve));if(!h(s,i)||i===s)throw new Error("--serve must name a built application directory inside the project root.");let d=await rt(s,i),c=await S(),w=et(e,r,t),f=se(z(n.runtime.three,t),q(e,r,t)),h$1=createServer((y,u)=>{(async()=>{if(_e(y,u,a,o,e!=="precompiled"))return;let p=new URL(y.url??"/","http://three-blocks.invalid");if(y.method!=="GET"&&y.method!=="HEAD"){u.statusCode=405,u.end("GET or HEAD required");return}let m=p.pathname===Te?c:p.pathname===ke?w:p.pathname===Ee?f: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(y.method==="HEAD"?void 0:m);return}let g=await nt(i,p.pathname);if(g===void 0){u.statusCode=404,u.end("Not found");return}let v=A.extname(g.file).toLowerCase(),b=v===".html"?Buffer.from(Ze(g.data.toString("utf8"))):g.data;u.statusCode=200,u.setHeader("Content-Type",Qe[v]??"application/octet-stream"),u.setHeader("Content-Length",String(b.byteLength)),u.setHeader("Cache-Control","no-store"),u.end(y.method==="HEAD"?void 0:b);})().catch(p=>{if(u.headersSent)return u.destroy(p instanceof Error?p:void 0);u.statusCode=500,u.end(p instanceof Error?p.message:String(p));});});await new Promise((y,u)=>{h$1.once("error",u),h$1.listen(0,"127.0.0.1",()=>{h$1.off("error",u),y();});});let S$1=h$1.address();if(!S$1||typeof S$1=="string")throw new Error("Static capture server did not expose an ephemeral TCP address.");return {server:h$1,baseUrl:`http://127.0.0.1:${S$1.port}`,transform:d}}a(at,"startStaticShaderServer");function st(n,e,t){return n===e?true:t&&n!==void 0&&n!=="capture"&&e!=="capture"}a(st,"canReuseShaderBrowserSession");function ve(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)}a(ve,"isRetryableShaderObservationNavigation");var N=class{static{a(this,"PlaywrightShaderDriver");}#e;#t=new ne;#n=new ae;#h;#m;#o;#i;#r;#a;#f;#l;#p;#w;#u=0;#c;constructor(e){this.#e=e;}#d(){return this.#h?.status??this.#m??{seen:false,applied:false,alreadyPresent:false}}async#g(e,t){if(this.#r?.isConnected()===true)return;this.#r=void 0;let r=await Ve();this.#c??=await mkdtemp(A.join(tmpdir(),"three-blocks-shader-cache-")),this.#r=await r.launch({headless:t==="webgl"?this.#e.headed!==true:pe(this.#e.headed===true),args:[...t==="webgl"?fe():me(),`--disk-cache-dir=${this.#c}`],timeout:e.timeoutMs}),this.#u=0;}async#s(e,t,r){let a;try{return await Promise.race([r(),new Promise((o,s)=>{a=setTimeout(()=>s(new Error(`launch: Timeout ${t.timeoutMs}ms exceeded.`)),t.timeoutMs);})])}catch(o){throw this.#r===e&&(this.#r=void 0),await M(()=>e.close()),o}finally{a!==void 0&&clearTimeout(a);}}async#y(e,t,r){let a=this.#o!==void 0||this.#i!==void 0||this.#e.url!==void 0&&this.#a!==void 0,o=this.#p===t&&(this.#i!==void 0?this.#l===e:st(this.#l,e,r.bridge.legacyLab));if(a&&o){this.#l=e,await this.#g(r,t);return}if(a&&await this.close(),this.#l=e,this.#p=t,this.#e.url!==void 0){let s=new URL(this.#e.url);if(!["http:","https:"].includes(s.protocol)||s.username||s.password||s.hash)throw new Error("Attached shader URL must be an HTTP(S) URL without credentials or a fragment.");this.#a=s.href,this.#m={seen:true,applied:true,alreadyPresent:false,captureApplied:true,id:"attached-application"},await this.#g(r,t);return}if(this.#e.serve!==void 0)try{let s=await at({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=s.server,this.#m=s.transform,this.#a=s.baseUrl,await this.#g(r,t);return}catch(s){throw await this.close(),s}this.#h=X(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.#f={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 s=await Je(this.#e.root);this.#o=await s({root:this.#e.root,logLevel:"error",plugins:[this.#h.plugin,ze(this.#t,this.#n,e!=="precompiled",z(this.#e.runtime.three,t),q(e,r,t))],server:{host:"127.0.0.1",port:0}}),await this.#o.listen();let i=this.#o.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.#g(r,t);}catch(s){throw await this.close(),s}}async capture(e,t,r="webgpu"){let a$2=Date.now();if(await this.#y("capture",r,t),!this.#r||!this.#a)throw new Error("Shader browser driver did not start.");let o=this.#r,s=await this.#s(o,t,()=>o.newContext({viewport:t.viewport}));this.#e.url!==void 0&&await this.#s(o,t,()=>te(s,this.#t,this.#n,"capture",t,r,z(this.#e.runtime.three,r)));let i=await this.#s(o,t,()=>s.newPage()),d=ee(i);this.#n.clear(e.key);let c=j(t),w=this.#t.wait(e.key,c),f=false;c>t.timeoutMs?(async()=>{let m=Math.min(5e3,Math.max(1e3,Math.round(t.timeoutMs/8))),g=Date.now(),v="",b="";for(;!f;){if(await new Promise(k=>setTimeout(k,m)),f)return;let T=this.#n.read(e.key),B=T===void 0?"":JSON.stringify(T);if(B!==v){v=B,g=Date.now();continue}if(Date.now()-g<t.timeoutMs)continue;let E=await xe(i,t.readiness.global);if(f)return;if(!E.alive||E.signature!==b){b=E.signature,g=Date.now();continue}this.#t.cancel(e.key,new Error(`Shader capture "${e.key}" timed out after ${t.timeoutMs}ms without progress (hard cap ${c}ms).`));return}})().catch(()=>{}):void 0;let S=Promise.race([w,d.first.then(m=>Promise.reject(m))]),y=a(()=>{},"resolveDisconnected"),u=new Promise(m=>{y=m;}),p=a(()=>y(new Error("Shader capture browser disconnected before posting a manifest.")),"onDisconnected");o.on("disconnected",p);try{let m=i.goto(ge(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}),g=await Ke(m,Promise.race([S,u.then(b=>Promise.reject(b))]));Y(this.#d());let v=[...d.page,...d.console];if(v.length>0)throw new Error(`Capture browser errors:
|
|
78
|
-
- ${v.join(`
|
|
79
|
-
- `)}`);return a$1(g)?{...g,timing:{...a$1(g.timing)?g.timing:{},launch:a$2,...this.#n.firstRequest(e.key)===void 0?{}:{firstRequest:this.#n.firstRequest(e.key)},posted:Date.now()}}:g}catch(m){let g=m instanceof Error?m:new Error(String(m));this.#t.cancel(e.key,g),await w.catch(()=>{});let v=this.#n.read(e.key);if(g.message.includes("timed out")){let b=await J(()=>i.evaluate(E=>{let k=globalThis,$=k.__threeBlocksShaderTools,Oe=$&&typeof $=="object"?$:void 0,Me=k.document,O=Reflect.get(k,Symbol.for("three-blocks.shader-capture.cache-value.v1")),I=k.location,Ae=I!==null&&typeof I=="object"&&typeof Reflect.get(I,"href")=="string"?String(Reflect.get(I,"href")):"http://three-blocks.invalid/",je=new URL(Ae).searchParams.get("captureId")??"default",oe=O!==null&&typeof O=="object"&&typeof Reflect.get(O,"registrations")=="function"?Reflect.apply(Reflect.get(O,"registrations"),O,[je]):void 0,ie=a(R=>{let _=k;for(let De of R.split(".")){if(_===null||typeof _!="object"&&typeof _!="function")return;_=Reflect.get(_,De);}return _},"resolveGlobal"),de=null,z=null;if(E!==null){let R=ie(E);de=R===true||R===false?R:R===void 0?"absent":R!==null&&typeof R.then=="function"?"promise":typeof R;try{let _=JSON.stringify(ie(`${E}Diagnostics`));z=typeof _=="string"?_.slice(0,2048):null;}catch{z=null;}}return {documentReadyState:Me?.readyState??null,parityTargetFrame:Number(k.__threeBlocksParityTargetFrame??0),parityCompletedFrame:Number(k.__threeBlocksParityCompletedFrame??0),readiness:Oe?.readiness??null,readinessGlobal:de,readinessDiagnostics:z,captureCache:O!==null&&typeof O=="object"?{activeScene:Reflect.get(O,"activeScene")??null,registrations:Array.isArray(oe)?oe.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,B=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(`${B}${g.message} Last capture state for "${e.key}": ${JSON.stringify({page:b,telemetry:v??null,transform:this.#d()})}`)}throw g}finally{f=true,o.off("disconnected",p),await M(()=>s.close()),this.#u++,(!o.isConnected()||this.#u>=(t.browserRelaunchScenes??8))&&(this.#r===o&&(this.#r=void 0),await M(()=>o.close()),this.#u=0);}}async observe(e,t,r,a,o="webgpu"){for(let s=0;s<2;s++)try{return await this.#S(e,o,t,r,a)}catch(i){if(s===0&&ve(i))continue;throw i}throw new Error(`Shader observation retry was exhausted for scene "${e.key}".`)}async#S(e,t,r,a,o){if(await this.#y(r,t,a),!this.#r||!this.#a)throw new Error("Shader browser driver did not start.");let s=this.#r,i=await this.#s(s,a,()=>s.newContext({viewport:a.viewport}));this.#e.url!==void 0&&await this.#s(s,a,()=>te(i,this.#t,this.#n,r,a,t,z(this.#e.runtime.three,t)));let d=await this.#s(s,a,()=>i.newPage()),c=ee(d);this.#n.clear(e.key);try{await d.goto(ge(this.#a,e,{threeBlocksShaderCapture:"1",threeBlocksShaderMode:r,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:j(a)}),c.first.then(u=>Promise.reject(u))]),W(await V(d,a.bridge.legacyLab),e,a.bridge.legacyLab,this.#d(),z(this.#e.runtime.three,t)),await Se(d,a,c),await Promise.race([d.waitForFunction(a.bridge.legacyLab?"true":"globalThis.__threeBlocksShaderTools?.readiness?.firstFrame === true",void 0,{timeout:j(a)}),c.first.then(u=>Promise.reject(u))]),await F(d,a,1);let w=Buffer.from(await d.screenshot({type:"png"})),f=e.parityFrames??a.parity.frames,h=await F(d,a,f,o),S=Buffer.from(await d.screenshot({type:"png"}));e.parityFrames!==void 0&&f<a.parity.frames&&await F(d,a,a.parity.frames-f);let y=W(await V(d,a.bridge.legacyLab),e,a.bridge.legacyLab,this.#d(),z(this.#e.runtime.three,t));return this.#w===void 0&&(this.#w=await d.evaluate(async u=>{if(u==="webgl"){let E=Reflect.get(globalThis,"document").querySelector("canvas")?.getContext("webgl2"),k=E?.getExtension("WEBGL_debug_renderer_info");return {adapter:E&&k?String(E.getParameter(k.UNMASKED_RENDERER_WEBGL)):"WebGL adapter",platform:navigator.platform||navigator.userAgent}}let p=Reflect.get(navigator,"gpu"),m=typeof p=="object"&&p!==null?Reflect.get(p,"requestAdapter"):void 0,g=typeof m=="function"?await Reflect.apply(m,p,[]):void 0,v=typeof g=="object"&&g!==null?Reflect.get(g,"info"):void 0,b=["description","device","architecture","vendor"].flatMap(T=>{let B=typeof v=="object"&&v!==null?Reflect.get(v,T):void 0;return typeof B=="string"&&B.length>0?[B]:[]});return {adapter:[...new Set(b)].join(" \xB7 ")||"WebGPU adapter",platform:navigator.platform||navigator.userAgent}},t)),{scene:e.key,mode:r,...y,frame:h,firstFrameScreenshot:w,screenshot:S,errors:[...c.page,...c.console]}}catch(w){let f=w instanceof Error?w:new Error(String(w));if(/(?:timed?\s*out|timeout)/iu.test(f.message)){let u=this.#n.read(e.key),p=await J(()=>d.evaluate(()=>{let m=globalThis,g=m.__threeBlocksShaderTools,v=g&&typeof g=="object"?g: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(`${f.message} Last ${r} state for "${e.key}": ${JSON.stringify({page:p,telemetry:u??null})}`)}let h=this.#n.read(e.key),y=(a$1(h)&&Array.isArray(h.demands)&&h.demands.length>0?JSON.stringify(h.demands).slice(0,6e3):void 0)??await J(()=>d.evaluate(u=>{let p=globalThis,m=Reflect.get(p,Symbol.for(u)),g=m!==null&&typeof m=="object"?Reflect.get(m,"readThreeBlocksShaderDemands"):void 0,v=typeof g=="function"?Reflect.apply(g,m,[]):void 0,b=p.__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 y=="string"?new Error(`${f.message}
|
|
80
|
-
${r} demands: ${y}`):f}finally{await M(()=>i.close());}}async observePublished(e,t,r="webgpu"){for(let a=0;a<2;a++)try{return await this.#b(e,r,t)}catch(o){if(a===0&&ve(o))continue;throw o}throw new Error(`Published shader observation retry was exhausted for scene "${e.key}".`)}async#b(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,o=await this.#s(a,r,()=>a.newContext({viewport:r.viewport}));this.#e.url!==void 0&&await this.#s(a,r,()=>te(o,this.#t,this.#n,"precompiled",r,t,z(this.#e.runtime.three,t)));let s=await this.#s(a,r,()=>o.newPage()),i=ee(s);this.#n.clear(e.key);try{await s.goto(Ye(this.#a,e,t),{waitUntil:"domcontentloaded",timeout:r.timeoutMs}),await Promise.race([s.waitForFunction(r.bridge.legacyLab?"globalThis.__threeBlocks?.compileEnd === true":"globalThis.__threeBlocksShaderTools?.readiness?.compileEnd === true",void 0,{timeout:j(r)}),i.first.then(h=>Promise.reject(h))]),await Se(s,r,i),W(await V(s,r.bridge.legacyLab),e,r.bridge.legacyLab,this.#d(),z(this.#e.runtime.three,t)),await F(s,r,2);let d=await be(s),c=await F(s,r,120),w=await be(s),f=W(await V(s,r.bridge.legacyLab),e,r.bridge.legacyLab,this.#d(),z(this.#e.runtime.three,t));return {scene:e.key,mode:"precompiled",...f,frame:c,firstFrameScreenshot:d,beforeScreenshot:d,screenshot:w,errors:[...i.page,...i.console]}}finally{await M(()=>o.close());}}timingEnvironment(){return this.#w??{adapter:this.#p==="webgl"?"WebGL adapter":"WebGPU adapter",platform:`${x.platform}/${x.arch}`}}async close(){this.#t.rejectAll(new Error("Shader browser driver closed.")),this.#r&&await M(()=>this.#r?.close()??Promise.resolve());let e=this.#o?.httpServer,t=e?Reflect.get(e,"closeAllConnections"):void 0;if(e&&typeof t=="function"&&Reflect.apply(t,e,[]),this.#o&&await M(()=>this.#o?.close()??Promise.resolve()),this.#i){let r=this.#i;r.closeAllConnections(),await M(()=>new Promise(a=>{r.close(()=>a());}));}if(this.#r=void 0,this.#o=void 0,this.#i=void 0,this.#a=void 0,this.#h=void 0,this.#m=void 0,this.#l=void 0,this.#p=void 0,this.#w=void 0,this.#u=0,this.#c!==void 0&&(await rm(this.#c,{recursive:true,force:true}),this.#c=void 0),this.#f){for(let[r,a]of Object.entries(this.#f))a===void 0?delete x.env[r]:x.env[r]=a;this.#f=void 0;}}};function Et(n){return new N(n)}a(Et,"createPlaywrightShaderDriver");function Pt(n){return new N(n)}a(Pt,"createStaticPlaywrightShaderDriver");function Ct(n){return new N(n)}a(Ct,"createAttachedPlaywrightShaderDriver");export{Le as a,it as b,me as c,pe as d,Ke as e,qe as f,se as g,st as h,ve as i,Et as j,Pt as k,Ct as l};
|
package/dist/chunk-W6UL2OW7.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {a as a$1}from'./chunk-HOZDD6PW.js';import t from'process';var i=Object.freeze([{id:"three-inspector-invalid-json",pattern:/is not valid JSON/iu},{id:"chromium-webgpu-experimental",pattern:/WebGPU is experimental/iu}]);function a(n){return i.some(e=>e.pattern.test(n))}a$1(a,"isDocumentedBrowserNoise");function l(n=t.env,e=t.platform){let s=n.THREE_BLOCKS_WEBGPU_BROWSER_ARGS?.split(/\s+/u).filter(Boolean);if(s&&s.length>0)return s;let o=["--enable-unsafe-webgpu"];return e==="darwin"&&o.push("--enable-gpu","--use-angle=metal"),e==="linux"&&o.push("--enable-features=Vulkan","--disable-vulkan-surface","--ignore-gpu-blocklist","--disable-gpu-driver-bug-workarounds","--disable-gpu-watchdog"),o}a$1(l,"webgpuBrowserArgs");function g(n=t.env){let e=n.THREE_BLOCKS_WEBGL_BROWSER_ARGS?.split(/\s+/u).filter(Boolean);return e&&e.length>0?e:["--use-angle=swiftshader","--enable-unsafe-swiftshader","--ignore-gpu-blocklist"]}a$1(g,"webglBrowserArgs");function p(n=false,e=t.env){return n!==true&&e.THREE_BLOCKS_SOFTWARE_WEBGPU!=="1"}a$1(p,"webgpuBrowserHeadless");export{a,l as b,g as c,p as d};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
export{e as captureShaders,d as inspectShaderMatrix,f as testShaders}from'./chunk-LUULHXFK.js';import'./chunk-4YRR36JN.js';import'./chunk-W6UL2OW7.js';import'./chunk-ZT6T2W4B.js';import'./chunk-NPLE7PPF.js';import'./chunk-65VEJRRT.js';import'./chunk-5L2VS3BN.js';import'./chunk-HOZDD6PW.js';
|