@forgeax/engine-runtime 0.1.21 → 0.1.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (410) hide show
  1. package/README.md +18 -9
  2. package/dist/__tests__/advance-animation-player.cases.unit.test.d.ts +2 -0
  3. package/dist/__tests__/advance-animation-player.cases.unit.test.d.ts.map +1 -0
  4. package/dist/__tests__/asset-registry-aabb.cases.unit.test.d.ts +2 -0
  5. package/dist/__tests__/asset-registry-aabb.cases.unit.test.d.ts.map +1 -0
  6. package/dist/__tests__/asset-registry-bootstrap.cases.unit.test.d.ts +2 -0
  7. package/dist/__tests__/asset-registry-bootstrap.cases.unit.test.d.ts.map +1 -0
  8. package/dist/__tests__/asset-registry-builtin-nineslice.cases.unit.test.d.ts +2 -0
  9. package/dist/__tests__/asset-registry-builtin-nineslice.cases.unit.test.d.ts.map +1 -0
  10. package/dist/__tests__/asset-registry-d9-tile-sampler-soft-warn.cases.unit.test.d.ts +2 -0
  11. package/dist/__tests__/asset-registry-d9-tile-sampler-soft-warn.cases.unit.test.d.ts.map +1 -0
  12. package/dist/__tests__/asset-registry-guid.cases.unit.test.d.ts +2 -0
  13. package/dist/__tests__/asset-registry-guid.cases.unit.test.d.ts.map +1 -0
  14. package/dist/__tests__/asset-registry-material-validate.cases.unit.test.d.ts +2 -0
  15. package/dist/__tests__/asset-registry-material-validate.cases.unit.test.d.ts.map +1 -0
  16. package/dist/__tests__/asset-registry-mesh-fail-fast.cases.unit.test.d.ts +2 -0
  17. package/dist/__tests__/asset-registry-mesh-fail-fast.cases.unit.test.d.ts.map +1 -0
  18. package/dist/__tests__/asset-registry-scene.cases.unit.test.d.ts +2 -0
  19. package/dist/__tests__/asset-registry-scene.cases.unit.test.d.ts.map +1 -0
  20. package/dist/__tests__/asset-registry-sprite-slices-validate.cases.unit.test.d.ts +2 -0
  21. package/dist/__tests__/asset-registry-sprite-slices-validate.cases.unit.test.d.ts.map +1 -0
  22. package/dist/__tests__/asset-renderer-assembly.cases.unit.test.d.ts +2 -0
  23. package/dist/__tests__/asset-renderer-assembly.cases.unit.test.d.ts.map +1 -0
  24. package/dist/__tests__/asset.cases.unit.test.d.ts +2 -0
  25. package/dist/__tests__/asset.cases.unit.test.d.ts.map +1 -0
  26. package/dist/__tests__/bloom-gating.cases.unit.test.d.ts +2 -0
  27. package/dist/__tests__/bloom-gating.cases.unit.test.d.ts.map +1 -0
  28. package/dist/__tests__/builtin-guid-ssot.cases.unit.test.d.ts +2 -0
  29. package/dist/__tests__/builtin-guid-ssot.cases.unit.test.d.ts.map +1 -0
  30. package/dist/__tests__/builtin-pack.cases.unit.test.d.ts +2 -0
  31. package/dist/__tests__/builtin-pack.cases.unit.test.d.ts.map +1 -0
  32. package/dist/__tests__/camera-antialias.cases.unit.test.d.ts +2 -0
  33. package/dist/__tests__/camera-antialias.cases.unit.test.d.ts.map +1 -0
  34. package/dist/__tests__/camera-bloom.cases.unit.test.d.ts +2 -0
  35. package/dist/__tests__/camera-bloom.cases.unit.test.d.ts.map +1 -0
  36. package/dist/__tests__/camera-clear-schema.cases.unit.test.d.ts +2 -0
  37. package/dist/__tests__/camera-clear-schema.cases.unit.test.d.ts.map +1 -0
  38. package/dist/__tests__/camera-ortho.cases.unit.test.d.ts +2 -0
  39. package/dist/__tests__/camera-ortho.cases.unit.test.d.ts.map +1 -0
  40. package/dist/__tests__/cluster-binner.cases.unit.test.d.ts +2 -0
  41. package/dist/__tests__/cluster-binner.cases.unit.test.d.ts.map +1 -0
  42. package/dist/__tests__/create-renderer-fallback-shader-manifest.cases.unit.test.d.ts +2 -0
  43. package/dist/__tests__/create-renderer-fallback-shader-manifest.cases.unit.test.d.ts.map +1 -0
  44. package/dist/__tests__/create-renderer-uniform-fallback.cases.unit.test.d.ts +2 -0
  45. package/dist/__tests__/create-renderer-uniform-fallback.cases.unit.test.d.ts.map +1 -0
  46. package/dist/__tests__/cubemap-upload.cases.unit.test.d.ts +2 -0
  47. package/dist/__tests__/cubemap-upload.cases.unit.test.d.ts.map +1 -0
  48. package/dist/__tests__/dev-import-transport.cases.unit.test.d.ts +2 -0
  49. package/dist/__tests__/dev-import-transport.cases.unit.test.d.ts.map +1 -0
  50. package/dist/__tests__/engine-metrics.cases.unit.test.d.ts +2 -0
  51. package/dist/__tests__/engine-metrics.cases.unit.test.d.ts.map +1 -0
  52. package/dist/__tests__/equirect-projection-error.cases.unit.test.d.ts +2 -0
  53. package/dist/__tests__/equirect-projection-error.cases.unit.test.d.ts.map +1 -0
  54. package/dist/__tests__/font-asset-load.cases.unit.test.d.ts +2 -0
  55. package/dist/__tests__/font-asset-load.cases.unit.test.d.ts.map +1 -0
  56. package/dist/__tests__/fxaa-intermediate-texture.cases.unit.test.d.ts +2 -0
  57. package/dist/__tests__/fxaa-intermediate-texture.cases.unit.test.d.ts.map +1 -0
  58. package/dist/__tests__/fxaa-pipeline.cases.unit.test.d.ts +2 -0
  59. package/dist/__tests__/fxaa-pipeline.cases.unit.test.d.ts.map +1 -0
  60. package/dist/__tests__/gpu-residency.cases.unit.test.d.ts +2 -0
  61. package/dist/__tests__/gpu-residency.cases.unit.test.d.ts.map +1 -0
  62. package/dist/__tests__/gpu-resource-release.cases.unit.test.d.ts +2 -0
  63. package/dist/__tests__/gpu-resource-release.cases.unit.test.d.ts.map +1 -0
  64. package/dist/__tests__/handle-quad.cases.unit.test.d.ts +2 -0
  65. package/dist/__tests__/handle-quad.cases.unit.test.d.ts.map +1 -0
  66. package/dist/__tests__/hdrp-bgl-slots.cases.unit.test.d.ts +2 -0
  67. package/dist/__tests__/hdrp-bgl-slots.cases.unit.test.d.ts.map +1 -0
  68. package/dist/__tests__/hdrp-grid-invalid.cases.unit.test.d.ts +2 -0
  69. package/dist/__tests__/hdrp-grid-invalid.cases.unit.test.d.ts.map +1 -0
  70. package/dist/__tests__/hdrp-index-list-overflow-once.cases.unit.test.d.ts +2 -0
  71. package/dist/__tests__/hdrp-index-list-overflow-once.cases.unit.test.d.ts.map +1 -0
  72. package/dist/__tests__/hdrp-light-budget.cases.unit.test.d.ts +2 -0
  73. package/dist/__tests__/hdrp-light-budget.cases.unit.test.d.ts.map +1 -0
  74. package/dist/__tests__/hdrp-pipeline-asset-config.cases.unit.test.d.ts +2 -0
  75. package/dist/__tests__/hdrp-pipeline-asset-config.cases.unit.test.d.ts.map +1 -0
  76. package/dist/__tests__/helpers/register-runtime-components.d.ts.map +1 -1
  77. package/dist/__tests__/helpers/register-scene-components.d.ts.map +1 -1
  78. package/dist/__tests__/helpers/renderer-device-loss-dawn.d.ts +25 -0
  79. package/dist/__tests__/helpers/renderer-device-loss-dawn.d.ts.map +1 -0
  80. package/dist/__tests__/helpers/standard-material-manifest.d.ts +0 -1
  81. package/dist/__tests__/helpers/standard-material-manifest.d.ts.map +1 -1
  82. package/dist/__tests__/ibl-pipeline-cache.cases.unit.test.d.ts +2 -0
  83. package/dist/__tests__/ibl-pipeline-cache.cases.unit.test.d.ts.map +1 -0
  84. package/dist/__tests__/lazy-catalog.cases.unit.test.d.ts +2 -0
  85. package/dist/__tests__/lazy-catalog.cases.unit.test.d.ts.map +1 -0
  86. package/dist/__tests__/load-by-guid-hdr.cases.unit.test.d.ts +2 -0
  87. package/dist/__tests__/load-by-guid-hdr.cases.unit.test.d.ts.map +1 -0
  88. package/dist/__tests__/load-by-guid-prod-material-parent.cases.unit.test.d.ts +2 -0
  89. package/dist/__tests__/load-by-guid-prod-material-parent.cases.unit.test.d.ts.map +1 -0
  90. package/dist/__tests__/load-by-guid-prod.cases.unit.test.d.ts +2 -0
  91. package/dist/__tests__/load-by-guid-prod.cases.unit.test.d.ts.map +1 -0
  92. package/dist/__tests__/loader-registry.cases.unit.test.d.ts +2 -0
  93. package/dist/__tests__/loader-registry.cases.unit.test.d.ts.map +1 -0
  94. package/dist/__tests__/m7-hdrp-demo-shape.cases.unit.test.d.ts +2 -0
  95. package/dist/__tests__/m7-hdrp-demo-shape.cases.unit.test.d.ts.map +1 -0
  96. package/dist/__tests__/mipmap-formula.cases.unit.test.d.ts +2 -0
  97. package/dist/__tests__/mipmap-formula.cases.unit.test.d.ts.map +1 -0
  98. package/dist/__tests__/mipmap-pipeline-cache.cases.unit.test.d.ts +2 -0
  99. package/dist/__tests__/mipmap-pipeline-cache.cases.unit.test.d.ts.map +1 -0
  100. package/dist/__tests__/parse-asset-payload-material.cases.unit.test.d.ts +2 -0
  101. package/dist/__tests__/parse-asset-payload-material.cases.unit.test.d.ts.map +1 -0
  102. package/dist/__tests__/parse-asset-payload-texture.cases.unit.test.d.ts +2 -0
  103. package/dist/__tests__/parse-asset-payload-texture.cases.unit.test.d.ts.map +1 -0
  104. package/dist/__tests__/parse-scene-payload-refs.cases.unit.test.d.ts +2 -0
  105. package/dist/__tests__/parse-scene-payload-refs.cases.unit.test.d.ts.map +1 -0
  106. package/dist/__tests__/pass-selector.cases.unit.test.d.ts +2 -0
  107. package/dist/__tests__/pass-selector.cases.unit.test.d.ts.map +1 -0
  108. package/dist/__tests__/pipeline-builder.cases.unit.test.d.ts +2 -0
  109. package/dist/__tests__/pipeline-builder.cases.unit.test.d.ts.map +1 -0
  110. package/dist/__tests__/pipeline-cache-key-topology.cases.unit.test.d.ts +2 -0
  111. package/dist/__tests__/pipeline-cache-key-topology.cases.unit.test.d.ts.map +1 -0
  112. package/dist/__tests__/pipeline-vertex-stride-branch.cases.unit.test.d.ts +2 -0
  113. package/dist/__tests__/pipeline-vertex-stride-branch.cases.unit.test.d.ts.map +1 -0
  114. package/dist/__tests__/pipeline.cases.unit.test.d.ts +2 -0
  115. package/dist/__tests__/pipeline.cases.unit.test.d.ts.map +1 -0
  116. package/dist/__tests__/post-process-register.cases.unit.test.d.ts +2 -0
  117. package/dist/__tests__/post-process-register.cases.unit.test.d.ts.map +1 -0
  118. package/dist/__tests__/propagate-transforms.cases.unit.test.d.ts +2 -0
  119. package/dist/__tests__/propagate-transforms.cases.unit.test.d.ts.map +1 -0
  120. package/dist/__tests__/record-all-topology.cases.unit.test.d.ts +2 -0
  121. package/dist/__tests__/record-all-topology.cases.unit.test.d.ts.map +1 -0
  122. package/dist/__tests__/record-draw-branch.cases.unit.test.d.ts +2 -0
  123. package/dist/__tests__/record-draw-branch.cases.unit.test.d.ts.map +1 -0
  124. package/dist/__tests__/record-strip-index-format.cases.unit.test.d.ts +2 -0
  125. package/dist/__tests__/record-strip-index-format.cases.unit.test.d.ts.map +1 -0
  126. package/dist/__tests__/register-with-guid-rgba16float.cases.unit.test.d.ts +2 -0
  127. package/dist/__tests__/register-with-guid-rgba16float.cases.unit.test.d.ts.map +1 -0
  128. package/dist/__tests__/render-data.cases.unit.test.d.ts +2 -0
  129. package/dist/__tests__/render-data.cases.unit.test.d.ts.map +1 -0
  130. package/dist/__tests__/render-error-exhaustive.test-d.d.ts.map +1 -1
  131. package/dist/__tests__/render-query-regression.cases.unit.test.d.ts +2 -0
  132. package/dist/__tests__/render-query-regression.cases.unit.test.d.ts.map +1 -0
  133. package/dist/__tests__/render-system-record-submesh.cases.unit.test.d.ts +2 -0
  134. package/dist/__tests__/render-system-record-submesh.cases.unit.test.d.ts.map +1 -0
  135. package/dist/__tests__/render-system-record-warn-once.cases.unit.test.d.ts +2 -0
  136. package/dist/__tests__/render-system-record-warn-once.cases.unit.test.d.ts.map +1 -0
  137. package/dist/__tests__/renderer-device-loss-multi-world.integration.test.d.ts +2 -0
  138. package/dist/__tests__/renderer-device-loss-multi-world.integration.test.d.ts.map +1 -0
  139. package/dist/__tests__/renderer-device-loss-provider-feasibility.dawn.test.d.ts +2 -0
  140. package/dist/__tests__/renderer-device-loss-provider-feasibility.dawn.test.d.ts.map +1 -0
  141. package/dist/__tests__/renderer-device-loss-recovery.dawn.test.d.ts +2 -0
  142. package/dist/__tests__/renderer-device-loss-recovery.dawn.test.d.ts.map +1 -0
  143. package/dist/__tests__/renderer-draw-world.cases.unit.test.d.ts +2 -0
  144. package/dist/__tests__/renderer-draw-world.cases.unit.test.d.ts.map +1 -0
  145. package/dist/__tests__/renderer-recovery-consumer.integration.test.d.ts +2 -0
  146. package/dist/__tests__/renderer-recovery-consumer.integration.test.d.ts.map +1 -0
  147. package/dist/__tests__/renderstate-pipeline-cache.cases.unit.test.d.ts +2 -0
  148. package/dist/__tests__/renderstate-pipeline-cache.cases.unit.test.d.ts.map +1 -0
  149. package/dist/__tests__/resolve-scene-guids.cases.unit.test.d.ts +2 -0
  150. package/dist/__tests__/resolve-scene-guids.cases.unit.test.d.ts.map +1 -0
  151. package/dist/__tests__/shadow-skip-non-triangle.cases.unit.test.d.ts +2 -0
  152. package/dist/__tests__/shadow-skip-non-triangle.cases.unit.test.d.ts.map +1 -0
  153. package/dist/__tests__/skin-errors-kebab-case.cases.unit.test.d.ts +2 -0
  154. package/dist/__tests__/skin-errors-kebab-case.cases.unit.test.d.ts.map +1 -0
  155. package/dist/__tests__/skin-instances-coexist.cases.unit.test.d.ts +2 -0
  156. package/dist/__tests__/skin-instances-coexist.cases.unit.test.d.ts.map +1 -0
  157. package/dist/__tests__/skin-m2-extract-happy.cases.unit.test.d.ts +2 -0
  158. package/dist/__tests__/skin-m2-extract-happy.cases.unit.test.d.ts.map +1 -0
  159. package/dist/__tests__/skin-m2-extract-joint-error.cases.unit.test.d.ts +2 -0
  160. package/dist/__tests__/skin-m2-extract-joint-error.cases.unit.test.d.ts.map +1 -0
  161. package/dist/__tests__/skin-m2-extract-null-assets.cases.unit.test.d.ts +2 -0
  162. package/dist/__tests__/skin-m2-extract-null-assets.cases.unit.test.d.ts.map +1 -0
  163. package/dist/__tests__/skin-m2-extract-skeleton-error.cases.unit.test.d.ts +2 -0
  164. package/dist/__tests__/skin-m2-extract-skeleton-error.cases.unit.test.d.ts.map +1 -0
  165. package/dist/__tests__/skin-m3-record-cache.cases.unit.test.d.ts +2 -0
  166. package/dist/__tests__/skin-m3-record-cache.cases.unit.test.d.ts.map +1 -0
  167. package/dist/__tests__/skin-palette-extract.cases.unit.test.d.ts +2 -0
  168. package/dist/__tests__/skin-palette-extract.cases.unit.test.d.ts.map +1 -0
  169. package/dist/__tests__/skin-pipeline-routing.cases.unit.test.d.ts +2 -0
  170. package/dist/__tests__/skin-pipeline-routing.cases.unit.test.d.ts.map +1 -0
  171. package/dist/__tests__/skin.cases.unit.test.d.ts +2 -0
  172. package/dist/__tests__/skin.cases.unit.test.d.ts.map +1 -0
  173. package/dist/__tests__/skybox-extract.cases.unit.test.d.ts +2 -0
  174. package/dist/__tests__/skybox-extract.cases.unit.test.d.ts.map +1 -0
  175. package/dist/__tests__/skybox-shader-compile.cases.unit.test.d.ts +2 -0
  176. package/dist/__tests__/skybox-shader-compile.cases.unit.test.d.ts.map +1 -0
  177. package/dist/__tests__/skylight-bind-group.cases.unit.test.d.ts +2 -0
  178. package/dist/__tests__/skylight-bind-group.cases.unit.test.d.ts.map +1 -0
  179. package/dist/__tests__/skylight-component.cases.unit.test.d.ts +2 -0
  180. package/dist/__tests__/skylight-component.cases.unit.test.d.ts.map +1 -0
  181. package/dist/__tests__/skylight-fallback-path.cases.unit.test.d.ts +2 -0
  182. package/dist/__tests__/skylight-fallback-path.cases.unit.test.d.ts.map +1 -0
  183. package/dist/__tests__/skylight-pipeline-layout.cases.unit.test.d.ts +2 -0
  184. package/dist/__tests__/skylight-pipeline-layout.cases.unit.test.d.ts.map +1 -0
  185. package/dist/__tests__/skylight-solid-color-extract.cases.unit.test.d.ts +2 -0
  186. package/dist/__tests__/skylight-solid-color-extract.cases.unit.test.d.ts.map +1 -0
  187. package/dist/__tests__/sprite-animation-tick-boundary.cases.unit.test.d.ts +2 -0
  188. package/dist/__tests__/sprite-animation-tick-boundary.cases.unit.test.d.ts.map +1 -0
  189. package/dist/__tests__/sprite-animation-tick-clamp.cases.unit.test.d.ts +2 -0
  190. package/dist/__tests__/sprite-animation-tick-clamp.cases.unit.test.d.ts.map +1 -0
  191. package/dist/__tests__/sprite-animation-tick-frame-duration-negative.cases.unit.test.d.ts +2 -0
  192. package/dist/__tests__/sprite-animation-tick-frame-duration-negative.cases.unit.test.d.ts.map +1 -0
  193. package/dist/__tests__/sprite-animation-tick-frame-duration-zero.cases.unit.test.d.ts +2 -0
  194. package/dist/__tests__/sprite-animation-tick-frame-duration-zero.cases.unit.test.d.ts.map +1 -0
  195. package/dist/__tests__/sprite-animation-tick-loop.cases.unit.test.d.ts +2 -0
  196. package/dist/__tests__/sprite-animation-tick-loop.cases.unit.test.d.ts.map +1 -0
  197. package/dist/__tests__/sprite-animation-tick-override-probe.cases.unit.test.d.ts +2 -0
  198. package/dist/__tests__/sprite-animation-tick-override-probe.cases.unit.test.d.ts.map +1 -0
  199. package/dist/__tests__/sprite-animation-tick-regions-mismatch.cases.unit.test.d.ts +2 -0
  200. package/dist/__tests__/sprite-animation-tick-regions-mismatch.cases.unit.test.d.ts.map +1 -0
  201. package/dist/__tests__/storage-buffer-caps.cases.unit.test.d.ts +2 -0
  202. package/dist/__tests__/storage-buffer-caps.cases.unit.test.d.ts.map +1 -0
  203. package/dist/__tests__/systems.cases.unit.test.d.ts +2 -0
  204. package/dist/__tests__/systems.cases.unit.test.d.ts.map +1 -0
  205. package/dist/__tests__/tonemap-hdr-target.cases.unit.test.d.ts +2 -0
  206. package/dist/__tests__/tonemap-hdr-target.cases.unit.test.d.ts.map +1 -0
  207. package/dist/__tests__/tonemap-pipeline-split.cases.unit.test.d.ts +2 -0
  208. package/dist/__tests__/tonemap-pipeline-split.cases.unit.test.d.ts.map +1 -0
  209. package/dist/__tests__/tonemap.cases.unit.test.d.ts +2 -0
  210. package/dist/__tests__/tonemap.cases.unit.test.d.ts.map +1 -0
  211. package/dist/__tests__/transparent-sort-config-get.cases.unit.test.d.ts +2 -0
  212. package/dist/__tests__/transparent-sort-config-get.cases.unit.test.d.ts.map +1 -0
  213. package/dist/__tests__/transparent-sort-config-set.cases.unit.test.d.ts +2 -0
  214. package/dist/__tests__/transparent-sort-config-set.cases.unit.test.d.ts.map +1 -0
  215. package/dist/__tests__/transparent-sort.cases.unit.test.d.ts +2 -0
  216. package/dist/__tests__/transparent-sort.cases.unit.test.d.ts.map +1 -0
  217. package/dist/__tests__/upload-texture-consistency.cases.unit.test.d.ts +2 -0
  218. package/dist/__tests__/upload-texture-consistency.cases.unit.test.d.ts.map +1 -0
  219. package/dist/__tests__/verify-revisions.cases.unit.test.d.ts +2 -0
  220. package/dist/__tests__/verify-revisions.cases.unit.test.d.ts.map +1 -0
  221. package/dist/__tests__/wire-default-loaders.cases.unit.test.d.ts +2 -0
  222. package/dist/__tests__/wire-default-loaders.cases.unit.test.d.ts.map +1 -0
  223. package/dist/__tests__/zero-camera-clear-fallback.cases.unit.test.d.ts +2 -0
  224. package/dist/__tests__/zero-camera-clear-fallback.cases.unit.test.d.ts.map +1 -0
  225. package/dist/createRenderer.d.ts.map +1 -1
  226. package/dist/dev-import-transport.d.ts.map +1 -1
  227. package/dist/index.mjs +4 -3
  228. package/dist/index.mjs.map +1 -1
  229. package/dist/sprite-param-values.d.ts +1 -1
  230. package/package.json +30 -30
  231. package/src/__tests__/advance-animation-player.cases.unit.test.ts +1666 -0
  232. package/src/__tests__/animation-graph-asset-union.test-d.ts +2 -0
  233. package/src/__tests__/asset-brand-and-name-retirement.test.ts +4 -3
  234. package/src/__tests__/asset-registry-aabb.cases.unit.test.ts +676 -0
  235. package/src/__tests__/asset-registry-bootstrap.cases.unit.test.ts +472 -0
  236. package/src/__tests__/asset-registry-builtin-nineslice.cases.unit.test.ts +481 -0
  237. package/src/__tests__/asset-registry-d9-tile-sampler-soft-warn.cases.unit.test.ts +568 -0
  238. package/src/__tests__/asset-registry-guid.cases.unit.test.ts +500 -0
  239. package/src/__tests__/asset-registry-material-validate.cases.unit.test.ts +756 -0
  240. package/src/__tests__/asset-registry-mesh-fail-fast.cases.unit.test.ts +591 -0
  241. package/src/__tests__/asset-registry-scene.cases.unit.test.ts +501 -0
  242. package/src/__tests__/asset-registry-scene.test-d.ts +1 -0
  243. package/src/__tests__/asset-registry-sprite-slices-validate.cases.unit.test.ts +536 -0
  244. package/src/__tests__/asset-renderer-assembly.cases.unit.test.ts +496 -0
  245. package/src/__tests__/asset.cases.unit.test.ts +439 -0
  246. package/src/__tests__/bind-group-cache-keying.test.ts +6 -2
  247. package/src/__tests__/bloom-gating.cases.unit.test.ts +428 -0
  248. package/src/__tests__/builtin-guid-ssot.cases.unit.test.ts +472 -0
  249. package/src/__tests__/builtin-pack.cases.unit.test.ts +639 -0
  250. package/src/__tests__/builtin-shader-register-e2e.test.ts +1 -1
  251. package/src/__tests__/camera-antialias.cases.unit.test.ts +372 -0
  252. package/src/__tests__/camera-bloom.cases.unit.test.ts +396 -0
  253. package/src/__tests__/camera-clear-schema.cases.unit.test.ts +391 -0
  254. package/src/__tests__/camera-ortho.cases.unit.test.ts +484 -0
  255. package/src/__tests__/cluster-binner.cases.unit.test.ts +817 -0
  256. package/src/__tests__/collect-scene-mount-collapse.test.ts +5 -1
  257. package/src/__tests__/collect-transient-roundtrip.test.ts +14 -3
  258. package/src/__tests__/components.test-d.ts +9 -6
  259. package/src/__tests__/components.unit.test.ts +23 -19
  260. package/src/__tests__/create-renderer-fallback-shader-manifest.cases.unit.test.ts +345 -0
  261. package/src/__tests__/create-renderer-uniform-fallback.cases.unit.test.ts +445 -0
  262. package/src/__tests__/cubemap-upload.cases.unit.test.ts +593 -0
  263. package/src/__tests__/dawn/ibl-precompute-readback.dawn.test.ts +184 -17
  264. package/src/__tests__/dawn/material-alpha.dawn.test.ts +17 -4
  265. package/src/__tests__/derive-bgl-integration.test.ts +8 -8
  266. package/src/__tests__/dev-import-transport.cases.unit.test.ts +503 -0
  267. package/src/__tests__/engine-metrics.cases.unit.test.ts +371 -0
  268. package/src/__tests__/equirect-projection-error.cases.unit.test.ts +416 -0
  269. package/src/__tests__/errors.unit.test.ts +3 -0
  270. package/src/__tests__/extract-frames-merge.test.ts +3 -0
  271. package/src/__tests__/font-asset-load.cases.unit.test.ts +510 -0
  272. package/src/__tests__/fxaa-intermediate-texture.cases.unit.test.ts +690 -0
  273. package/src/__tests__/fxaa-pipeline.cases.unit.test.ts +546 -0
  274. package/src/__tests__/gpu-residency.cases.unit.test.ts +479 -0
  275. package/src/__tests__/gpu-resource-release.cases.unit.test.ts +929 -0
  276. package/src/__tests__/handle-quad.cases.unit.test.ts +491 -0
  277. package/src/__tests__/hdrp-bgl-slots.cases.unit.test.ts +451 -0
  278. package/src/__tests__/hdrp-grid-invalid.cases.unit.test.ts +408 -0
  279. package/src/__tests__/hdrp-index-list-overflow-once.cases.unit.test.ts +405 -0
  280. package/src/__tests__/hdrp-light-budget.cases.unit.test.ts +483 -0
  281. package/src/__tests__/hdrp-pipeline-asset-config.cases.unit.test.ts +441 -0
  282. package/src/__tests__/helpers/register-runtime-components.ts +9 -1
  283. package/src/__tests__/helpers/register-scene-components.ts +9 -2
  284. package/src/__tests__/helpers/renderer-device-loss-dawn.ts +69 -0
  285. package/src/__tests__/helpers/standard-material-manifest.ts +11 -15
  286. package/src/__tests__/ibl-pipeline-cache.cases.unit.test.ts +415 -0
  287. package/src/__tests__/lazy-catalog.cases.unit.test.ts +848 -0
  288. package/src/__tests__/light-gpu-byte-neutral.unit.test.ts +14 -15
  289. package/src/__tests__/light-snapshot.test-d.ts +27 -1
  290. package/src/__tests__/lights-preservation.fixup.test.ts +19 -21
  291. package/src/__tests__/lights.unit.test.ts +2076 -1
  292. package/src/__tests__/load-by-guid-hdr.cases.unit.test.ts +582 -0
  293. package/src/__tests__/load-by-guid-prod-material-parent.cases.unit.test.ts +1514 -0
  294. package/src/__tests__/load-by-guid-prod.cases.unit.test.ts +557 -0
  295. package/src/__tests__/loader-name-survival.test.ts +8 -9
  296. package/src/__tests__/loader-registry.cases.unit.test.ts +767 -0
  297. package/src/__tests__/m7-hdrp-demo-shape.cases.unit.test.ts +361 -0
  298. package/src/__tests__/material-texture-uv-scale.unit.test.ts +2 -2
  299. package/src/__tests__/materials.unit.test.ts +29 -10
  300. package/src/__tests__/mipmap-formula.cases.unit.test.ts +434 -0
  301. package/src/__tests__/mipmap-pipeline-cache.cases.unit.test.ts +490 -0
  302. package/src/__tests__/package-promotion.test.ts +7 -11
  303. package/src/__tests__/parse-asset-payload-material.cases.unit.test.ts +565 -0
  304. package/src/__tests__/parse-asset-payload-texture.cases.unit.test.ts +720 -0
  305. package/src/__tests__/parse-scene-payload-refs.cases.unit.test.ts +767 -0
  306. package/src/__tests__/pass-selector.cases.unit.test.ts +376 -0
  307. package/src/__tests__/pbr-pipeline.unit.test.ts +39 -21
  308. package/src/__tests__/pipeline-builder.cases.unit.test.ts +624 -0
  309. package/src/__tests__/pipeline-cache-key-topology.cases.unit.test.ts +807 -0
  310. package/src/__tests__/pipeline-vertex-stride-branch.cases.unit.test.ts +379 -0
  311. package/src/__tests__/pipeline.cases.unit.test.ts +370 -0
  312. package/src/__tests__/point-light-shadow.browser.test.ts +1 -0
  313. package/src/__tests__/point-light-shadow.unit.test.ts +18 -98
  314. package/src/__tests__/post-process-register.cases.unit.test.ts +405 -0
  315. package/src/__tests__/propagate-transforms.cases.unit.test.ts +502 -0
  316. package/src/__tests__/propagate-transforms.dawn.test.ts +34 -18
  317. package/src/__tests__/record-all-topology.cases.unit.test.ts +608 -0
  318. package/src/__tests__/record-draw-branch.cases.unit.test.ts +621 -0
  319. package/src/__tests__/record-strip-index-format.cases.unit.test.ts +419 -0
  320. package/src/__tests__/record-worldid-isolation.test.ts +16 -32
  321. package/src/__tests__/register-with-guid-rgba16float.cases.unit.test.ts +469 -0
  322. package/src/__tests__/render-data.cases.unit.test.ts +553 -0
  323. package/src/__tests__/render-error-exhaustive.test-d.ts +11 -0
  324. package/src/__tests__/render-query-regression.cases.unit.test.ts +531 -0
  325. package/src/__tests__/render-system-extract.test.ts +5 -5
  326. package/src/__tests__/render-system-record-multi-material-textureview.test.ts +1 -0
  327. package/src/__tests__/render-system-record-per-submesh-transparency.test.ts +1 -0
  328. package/src/__tests__/render-system-record-submesh.cases.unit.test.ts +740 -0
  329. package/src/__tests__/render-system-record-warn-once.cases.unit.test.ts +418 -0
  330. package/src/__tests__/render-system-record.test.ts +15 -33
  331. package/src/__tests__/renderer-device-loss-multi-world.integration.test.ts +103 -0
  332. package/src/__tests__/renderer-device-loss-provider-feasibility.dawn.test.ts +124 -0
  333. package/src/__tests__/renderer-device-loss-recovery.dawn.test.ts +50 -0
  334. package/src/__tests__/renderer-draw-world.cases.unit.test.ts +514 -0
  335. package/src/__tests__/renderer-recovery-consumer.integration.test.ts +96 -0
  336. package/src/__tests__/renderer-surface.unit.test.ts +0 -2
  337. package/src/__tests__/renderstate-pipeline-cache.cases.unit.test.ts +631 -0
  338. package/src/__tests__/resolve-scene-guids.cases.unit.test.ts +1123 -0
  339. package/src/__tests__/resolveName-unified-entry.test.ts +6 -6
  340. package/src/__tests__/resolveName.test.ts +14 -2
  341. package/src/__tests__/shadow-caster-empty-schema.test.ts +1 -1
  342. package/src/__tests__/shadow-csm-cascade-loadop.test.ts +1 -0
  343. package/src/__tests__/shadow-csm-tile-consistency.test.ts +1 -0
  344. package/src/__tests__/shadow-csm-ubo.test.ts +3 -1
  345. package/src/__tests__/shadow-fields-observable.dawn.test.ts +15 -4
  346. package/src/__tests__/shadow-m1.dawn.test.ts +1 -1
  347. package/src/__tests__/shadow-skip-non-triangle.cases.unit.test.ts +681 -0
  348. package/src/__tests__/skin-errors-kebab-case.cases.unit.test.ts +475 -0
  349. package/src/__tests__/skin-extract-getarrayview-count.unit.test.ts +5 -4
  350. package/src/__tests__/skin-instances-coexist.cases.unit.test.ts +375 -0
  351. package/src/__tests__/skin-m2-extract-happy.cases.unit.test.ts +592 -0
  352. package/src/__tests__/skin-m2-extract-joint-error.cases.unit.test.ts +619 -0
  353. package/src/__tests__/skin-m2-extract-null-assets.cases.unit.test.ts +569 -0
  354. package/src/__tests__/skin-m2-extract-skeleton-error.cases.unit.test.ts +585 -0
  355. package/src/__tests__/skin-m3-record-cache.cases.unit.test.ts +457 -0
  356. package/src/__tests__/skin-palette-extract.cases.unit.test.ts +635 -0
  357. package/src/__tests__/skin-parented-double-transform.test.ts +5 -5
  358. package/src/__tests__/skin-pipeline-routing.cases.unit.test.ts +411 -0
  359. package/src/__tests__/skin.cases.unit.test.ts +421 -0
  360. package/src/__tests__/skinned-shadow-mixed.dawn.test.ts +1 -6
  361. package/src/__tests__/skybox-extract.cases.unit.test.ts +511 -0
  362. package/src/__tests__/skybox-shader-compile.cases.unit.test.ts +437 -0
  363. package/src/__tests__/skylight-bind-group.cases.unit.test.ts +642 -0
  364. package/src/__tests__/skylight-component.cases.unit.test.ts +386 -0
  365. package/src/__tests__/skylight-fallback-path.cases.unit.test.ts +566 -0
  366. package/src/__tests__/skylight-lazy-projection.test.ts +35 -20
  367. package/src/__tests__/skylight-pipeline-layout.cases.unit.test.ts +506 -0
  368. package/src/__tests__/skylight-solid-color-extract.cases.unit.test.ts +399 -0
  369. package/src/__tests__/sprite-animation-tick-boundary.cases.unit.test.ts +521 -0
  370. package/src/__tests__/sprite-animation-tick-clamp.cases.unit.test.ts +453 -0
  371. package/src/__tests__/sprite-animation-tick-frame-duration-negative.cases.unit.test.ts +447 -0
  372. package/src/__tests__/sprite-animation-tick-frame-duration-zero.cases.unit.test.ts +395 -0
  373. package/src/__tests__/sprite-animation-tick-loop.cases.unit.test.ts +494 -0
  374. package/src/__tests__/sprite-animation-tick-override-probe.cases.unit.test.ts +439 -0
  375. package/src/__tests__/sprite-animation-tick-regions-mismatch.cases.unit.test.ts +466 -0
  376. package/src/__tests__/sprite-lit-bgl-byte-identical.test.ts +16 -18
  377. package/src/__tests__/sprite-lit-pipeline-cache-key.test.ts +1 -1
  378. package/src/__tests__/ssao-bgl.test.ts +2 -1
  379. package/src/__tests__/ssao-pipelines.test.ts +1 -1
  380. package/src/__tests__/storage-buffer-caps.cases.unit.test.ts +373 -0
  381. package/src/__tests__/systems.cases.unit.test.ts +425 -0
  382. package/src/__tests__/template-game-default-api-contract.test.ts +45 -23
  383. package/src/__tests__/tilemap-chunk-extract.overhang-bounds.test.ts +1 -1
  384. package/src/__tests__/tilemap-chunk-extract.propagate-order.test.ts +10 -4
  385. package/src/__tests__/tonemap-hdr-target.cases.unit.test.ts +670 -0
  386. package/src/__tests__/tonemap-pipeline-split.cases.unit.test.ts +867 -0
  387. package/src/__tests__/tonemap.cases.unit.test.ts +446 -0
  388. package/src/__tests__/transform-hierarchy-pixel-diff.dawn.test.ts +2 -2
  389. package/src/__tests__/transparent-sort-config-get.cases.unit.test.ts +395 -0
  390. package/src/__tests__/transparent-sort-config-set.cases.unit.test.ts +424 -0
  391. package/src/__tests__/transparent-sort.cases.unit.test.ts +684 -0
  392. package/src/__tests__/upload-texture-consistency.cases.unit.test.ts +478 -0
  393. package/src/__tests__/verify-revisions.cases.unit.test.ts +619 -0
  394. package/src/__tests__/wire-default-loaders.cases.unit.test.ts +461 -0
  395. package/src/__tests__/zero-camera-clear-fallback.cases.unit.test.ts +374 -0
  396. package/src/collect-scene-asset.ts +1 -1
  397. package/src/components/__tests__/transform-vec-schema.test.ts +2 -2
  398. package/src/createRenderer.ts +1 -0
  399. package/src/dev-import-transport.ts +2 -1
  400. package/src/sprite-param-values.ts +1 -1
  401. package/dist/.tsbuildinfo +0 -1
  402. package/dist/__tests__/asset.unit.test.d.ts +0 -2
  403. package/dist/__tests__/asset.unit.test.d.ts.map +0 -1
  404. package/dist/__tests__/pipeline.unit.test.d.ts +0 -2
  405. package/dist/__tests__/pipeline.unit.test.d.ts.map +0 -1
  406. package/dist/__tests__/systems.unit.test.d.ts +0 -2
  407. package/dist/__tests__/systems.unit.test.d.ts.map +0 -1
  408. package/src/__tests__/asset.unit.test.ts +0 -7110
  409. package/src/__tests__/pipeline.unit.test.ts +0 -5283
  410. package/src/__tests__/systems.unit.test.ts +0 -9210
@@ -0,0 +1,767 @@
1
+ // @ts-nocheck — merged file: cross-source type narrowing failures from blocks originally outside src/ rootDir
2
+ // Consolidated by feat-20260609-test-pool-startup-reduction-merge-tiny-test-files
3
+ // biome-ignore-all lint/complexity/noUselessLoneBlockStatements: block-scope isolation between merged source files (consolidation paradigm)
4
+ //
5
+ // Source files (N=33):
6
+ // - packages/runtime/__tests__/asset-registry.test.ts
7
+ // - packages/runtime/__tests__/loader-registry.test.ts
8
+ // - packages/runtime/__tests__/wire-default-loaders.test.ts
9
+ // - packages/runtime/src/__tests__/asset-registry-aabb.test.ts
10
+ // - packages/runtime/src/__tests__/asset-registry-builtin-nineslice.test.ts
11
+ // - packages/runtime/src/__tests__/asset-registry-d9-tile-sampler-soft-warn.test.ts
12
+ // - packages/runtime/src/__tests__/asset-registry-guid.test.ts
13
+ // - packages/runtime/src/__tests__/asset-registry-material-validate.test.ts
14
+ // - packages/runtime/src/__tests__/asset-registry-mesh-fail-fast.test.ts
15
+ // - packages/runtime/src/__tests__/asset-registry-scene.test.ts
16
+ // - packages/runtime/src/__tests__/asset-registry-sprite-slices-validate.test.ts
17
+ // - packages/runtime/src/__tests__/auto-select.test.ts
18
+ // - packages/runtime/src/__tests__/bindgroup-resize-invalidation.test.ts
19
+ // - packages/runtime/src/__tests__/builtin-guid-ssot.test.ts
20
+ // - packages/runtime/src/__tests__/builtin-pack.test.ts
21
+ // - packages/runtime/src/__tests__/cube-texture-narrowing.test.ts
22
+ // - packages/runtime/src/__tests__/cubemap-upload.test.ts
23
+ // - packages/runtime/src/__tests__/dev-import-transport.test.ts
24
+ // - packages/runtime/src/__tests__/font-asset-load.test.ts
25
+ // - packages/runtime/src/__tests__/handle-quad.test.ts
26
+ // - packages/runtime/src/__tests__/lazy-catalog.test.ts
27
+ // - packages/runtime/src/__tests__/load-by-guid-hdr.test.ts
28
+ // - packages/runtime/src/__tests__/load-by-guid-prod-material-parent.test.ts
29
+ // - packages/runtime/src/__tests__/load-by-guid-prod.test.ts
30
+ // - packages/runtime/src/__tests__/mipmap-formula.test.ts
31
+ // - packages/runtime/src/__tests__/mipmap-pipeline-cache.test.ts
32
+ // - packages/runtime/src/__tests__/parse-asset-payload-material.test.ts
33
+ // - packages/runtime/src/__tests__/parse-asset-payload-texture.test.ts
34
+ // - packages/runtime/src/__tests__/parse-scene-payload-refs.test.ts
35
+ // - packages/runtime/src/__tests__/register-with-guid-rgba16float.test.ts
36
+ // - packages/runtime/src/__tests__/resolve-scene-guids.test.ts
37
+ // - packages/runtime/src/__tests__/upload-texture-consistency.test.ts
38
+ // - packages/runtime/src/__tests__/verify-revisions.test.ts
39
+ //
40
+ // Paradigm: each block-scope wraps a source file. ancestorTitles[0] is the
41
+ // source-preserved inner describe (NOT the source filename for these 3 files
42
+ // — recovery path: vitest report ancestorTitles -> grep this file -> upstream
43
+ // `// ─── from <name>.test.ts ───` block separator -> source filename).
44
+ // Top-level imports merged + deduped.
45
+
46
+ import { readFileSync } from 'node:fs';
47
+ import { fileURLToPath } from 'node:url';
48
+ import * as assetRegistryModule from '@forgeax/engine-assets-runtime';
49
+ import {
50
+ AssetRegistry,
51
+ animationClipLoader,
52
+ buildSceneChildContext,
53
+ fontLoader,
54
+ getOrCreateMipmapPipeline,
55
+ HANDLE_CUBE,
56
+ HANDLE_CYLINDER,
57
+ HANDLE_QUAD,
58
+ HANDLE_SPHERE,
59
+ HANDLE_TRIANGLE,
60
+ INLINE_PACK_LOADERS,
61
+ LoaderRegistry,
62
+ materialLoader,
63
+ meshLoader,
64
+ mipmapCacheSize,
65
+ numMipLevels,
66
+ PACK_ARTIFACT_LOADERS,
67
+ resolveAssetHandle,
68
+ sceneLoader,
69
+ skeletonLoader,
70
+ skinLoader,
71
+ textureLoader,
72
+ walkMaterialPassesOverSharedRefs,
73
+ wireDefaultLoaders,
74
+ } from '@forgeax/engine-assets-runtime';
75
+ import { audioLoader } from '@forgeax/engine-audio-webaudio';
76
+ import { defineComponent, World } from '@forgeax/engine-ecs';
77
+ import {
78
+ createBoxGeometry,
79
+ createPlaneGeometry,
80
+ meshFromInterleaved,
81
+ PROCEDURAL_FLOATS_PER_VERTEX,
82
+ } from '@forgeax/engine-geometry';
83
+ import { AssetGuid } from '@forgeax/engine-pack/guid';
84
+ import { ok, ok as rhiOk } from '@forgeax/engine-rhi';
85
+ import { rhi } from '@forgeax/engine-rhi-null';
86
+ import { ShaderRegistry } from '@forgeax/engine-shader';
87
+ import type {
88
+ EquirectAsset,
89
+ Handle,
90
+ MaterialAsset,
91
+ MaterialPass,
92
+ SamplerAsset,
93
+ } from '@forgeax/engine-types';
94
+ import { AssetError, toShared, toUnique, unwrapHandle } from '@forgeax/engine-types';
95
+ import { afterEach, beforeEach, describe, expect, expectTypeOf, it, vi } from 'vitest';
96
+ import { deriveBuiltin } from '../../../pack/src/builtin';
97
+ import { DeviceScope } from '../../../render/src/device/device-scope';
98
+ import { GpuResidencyCache } from '../../../render/src/device/gpu-residency';
99
+ import { createEngineMetrics } from '../../../render/src/engine-metrics';
100
+ import { createRenderer as createRuntimeRenderer } from '../createRenderer';
101
+ import { createDevImportTransport, type ImportTransport } from '../dev-import-transport';
102
+ import { EngineEnvironmentError } from '../errors/environment';
103
+ import { makeMockShaderRegistry } from './helpers/mock-shader-registry';
104
+ import { requireRenderer } from './renderer-test-utils';
105
+
106
+ vi.mock('@forgeax/engine-rhi-webgpu', async () => {
107
+ spies.webgpuImportCount += 1;
108
+ const actualRhi =
109
+ await vi.importActual<typeof import('@forgeax/engine-rhi')>('@forgeax/engine-rhi');
110
+ spies.rhiErrorCtor = actualRhi.RhiError;
111
+ const fakeAdapter = {
112
+ features: new Set<string>(),
113
+ limits: {} as Readonly<Record<string, number>>,
114
+ async requestDevice() {
115
+ return actualRhi.ok(makeFakeRhiDevice());
116
+ },
117
+ };
118
+ return {
119
+ rhi: {
120
+ requestAdapter: async () => {
121
+ if (spies.rhiWebgpuRequestAdapterShould === 'reject-rhi-not-available') {
122
+ return actualRhi.err(
123
+ new actualRhi.RhiError({
124
+ code: 'rhi-not-available',
125
+ expected: 'navigator.gpu available',
126
+ hint: 'unit-test: forced rhi-not-available',
127
+ }),
128
+ );
129
+ }
130
+ if (spies.rhiWebgpuRequestAdapterShould === 'reject-adapter-null') {
131
+ return actualRhi.err(
132
+ new actualRhi.RhiError({
133
+ code: 'adapter-unavailable',
134
+ expected: 'requestAdapter returns non-null',
135
+ hint: 'unit-test: forced adapter-unavailable',
136
+ }),
137
+ );
138
+ }
139
+ return actualRhi.ok(fakeAdapter);
140
+ },
141
+ acquireCanvasContext: (_canvas: unknown) => {
142
+ return actualRhi.ok({
143
+ configure: () => actualRhi.ok(undefined),
144
+ unconfigure: () => actualRhi.ok(undefined),
145
+ getCurrentTexture: () => actualRhi.ok({ __brand: 'TextureView' }),
146
+ });
147
+ },
148
+ },
149
+ createShaderModule: async () => actualRhi.ok({ __brand: 'ShaderModule' } as unknown as object),
150
+ translateErrorEventToRhiError: () =>
151
+ actualRhi.err(
152
+ new actualRhi.RhiError({
153
+ code: 'webgpu-runtime-error',
154
+ expected: 'GPU error event translates to RhiError',
155
+ hint: 'unit-test mock event translation',
156
+ }),
157
+ ),
158
+ _internal_getRawDevice: () => undefined,
159
+ };
160
+ });
161
+ vi.mock('@forgeax/engine-rhi-wgpu', async () => {
162
+ spies.wgpuImportCount += 1;
163
+ const actualRhi =
164
+ await vi.importActual<typeof import('@forgeax/engine-rhi')>('@forgeax/engine-rhi');
165
+ const fakeAdapter = {
166
+ features: new Set<string>(),
167
+ limits: {} as Readonly<Record<string, number>>,
168
+ async requestDevice() {
169
+ return actualRhi.ok(makeFakeRhiDevice());
170
+ },
171
+ };
172
+ return {
173
+ rhi: {
174
+ requestAdapter: async () => {
175
+ if (spies.rhiWgpuRequestAdapterShould === 'reject-rhi-not-available') {
176
+ return actualRhi.err(
177
+ new actualRhi.RhiError({
178
+ code: 'rhi-not-available',
179
+ expected: 'wgpu webgl backend available',
180
+ hint: 'unit-test: forced rhi-not-available on rhi-wgpu',
181
+ }),
182
+ );
183
+ }
184
+ return actualRhi.ok(fakeAdapter);
185
+ },
186
+ acquireCanvasContext: (_canvas: unknown) => {
187
+ return actualRhi.ok({
188
+ configure: () => actualRhi.ok(undefined),
189
+ unconfigure: () => actualRhi.ok(undefined),
190
+ getCurrentTexture: () => actualRhi.ok({ __brand: 'TextureView' }),
191
+ });
192
+ },
193
+ },
194
+ ensureReady: async () => {
195
+ spies.ensureReadyCount += 1;
196
+ if (spies.rhiWgpuEnsureReadyShould === 'reject-load-failed') {
197
+ throw new Error('unit-test: forced rhi-wgpu wasm load failure');
198
+ }
199
+ return undefined;
200
+ },
201
+ createShaderModule: async () => actualRhi.ok({ __brand: 'ShaderModule' } as unknown as object),
202
+ translateErrorEventToRhiError: () =>
203
+ actualRhi.err(
204
+ new actualRhi.RhiError({
205
+ code: 'webgpu-runtime-error',
206
+ expected: 'GPU error event translates to RhiError',
207
+ hint: 'unit-test mock event translation',
208
+ }),
209
+ ),
210
+ _internal_getRawDevice: () => undefined,
211
+ };
212
+ });
213
+ const spies = vi.hoisted(() => ({
214
+ webgpuImportCount: 0,
215
+ wgpuImportCount: 0,
216
+ ensureReadyCount: 0,
217
+ // Failure toggles set by individual tests before invoking createRenderer.
218
+ rhiWebgpuRequestAdapterShould: 'success' as
219
+ | 'success'
220
+ | 'reject-rhi-not-available'
221
+ | 'reject-adapter-null',
222
+ rhiWgpuEnsureReadyShould: 'success' as 'success' | 'reject-load-failed',
223
+ rhiWgpuRequestAdapterShould: 'success' as 'success' | 'reject-rhi-not-available',
224
+ rhiErrorCtor: undefined as undefined | (new (...args: never[]) => Error),
225
+ reset(): void {
226
+ this.webgpuImportCount = 0;
227
+ this.wgpuImportCount = 0;
228
+ this.ensureReadyCount = 0;
229
+ this.rhiWebgpuRequestAdapterShould = 'success';
230
+ this.rhiWgpuEnsureReadyShould = 'success';
231
+ this.rhiWgpuRequestAdapterShould = 'success';
232
+ },
233
+ }));
234
+ function makeFakeRhiDevice(): Record<string, unknown> {
235
+ let resolveLost!: (info: unknown) => void;
236
+ const lost = new Promise<unknown>((res) => {
237
+ resolveLost = res;
238
+ });
239
+ void resolveLost;
240
+ return {
241
+ __brand: 'RhiDevice',
242
+ lost,
243
+ features: new Set<string>(),
244
+ limits: {},
245
+ // feat-20260707 M5 / w33: createRenderer projects RhiCaps.textureCompression*
246
+ // into TranscodeCaps right after building the registry, so the fake device
247
+ // must expose a caps object (the real RhiDevice always carries one).
248
+ caps: {
249
+ textureCompressionBc: false,
250
+ textureCompressionEtc2: false,
251
+ textureCompressionAstc: false,
252
+ },
253
+ queue: {
254
+ submit: () => undefined,
255
+ writeBuffer: () => undefined,
256
+ },
257
+ createBuffer: () => ({ ok: true, value: { __brand: 'Buffer' } }),
258
+ createTexture: () => ({ ok: true, value: { __brand: 'Texture' } }),
259
+ createBindGroupLayout: () => ({ ok: true, value: { __brand: 'BindGroupLayout' } }),
260
+ createBindGroup: () => ({ ok: true, value: { __brand: 'BindGroup' } }),
261
+ createPipelineLayout: () => ({ ok: true, value: { __brand: 'PipelineLayout' } }),
262
+ createRenderPipeline: () => ({ ok: true, value: { __brand: 'RenderPipeline' } }),
263
+ createSampler: () => ({ ok: true, value: { __brand: 'Sampler' } }),
264
+ createShaderModule: () => ({
265
+ ok: true,
266
+ value: { __brand: 'ShaderModule' },
267
+ }),
268
+ createTextureView: () => ({ ok: true, value: { __brand: 'TextureView' } }),
269
+ createCommandEncoder: () => ({
270
+ ok: true,
271
+ value: {
272
+ beginRenderPass: () => ({
273
+ setPipeline: () => undefined,
274
+ setBindGroup: () => undefined,
275
+ setVertexBuffer: () => undefined,
276
+ setIndexBuffer: () => undefined,
277
+ draw: () => undefined,
278
+ drawIndexed: () => undefined,
279
+ end: () => undefined,
280
+ }),
281
+ finish: () => ({ __brand: 'CommandBuffer' }),
282
+ },
283
+ }),
284
+ };
285
+ }
286
+ function makeMockCanvas(opts: { webgpu?: 'context' | 'null'; webgl2?: 'context' | 'null' }) {
287
+ return {
288
+ width: 800,
289
+ height: 600,
290
+ getContext(kind: string): unknown {
291
+ if (kind === 'webgpu') {
292
+ if (opts.webgpu === 'context') {
293
+ return {
294
+ __mockTag: 'webgpu-canvas-context',
295
+ configure: () => undefined,
296
+ unconfigure: () => undefined,
297
+ getCurrentTexture: () => ({ createView: () => ({}) }),
298
+ };
299
+ }
300
+ return null;
301
+ }
302
+ if (kind === 'webgl2') {
303
+ if (opts.webgl2 === 'context') {
304
+ return {
305
+ __mockTag: 'webgl2',
306
+ getExtension: () => null,
307
+ getParameter: () => 1,
308
+ isContextLost: () => false,
309
+ };
310
+ }
311
+ return null;
312
+ }
313
+ return null;
314
+ },
315
+ addEventListener() {},
316
+ removeEventListener() {},
317
+ } as unknown as HTMLCanvasElement;
318
+ }
319
+ function _makeStubGPU(): unknown {
320
+ return {
321
+ requestAdapter: async () => ({
322
+ features: new Set<string>(),
323
+ limits: {},
324
+ requestDevice: async () => makeFakeRhiDevice(),
325
+ }),
326
+ getPreferredCanvasFormat: () => 'bgra8unorm',
327
+ };
328
+ }
329
+
330
+ void [
331
+ AssetError,
332
+ AssetGuid,
333
+ AssetRegistry,
334
+ DeviceScope,
335
+ EngineEnvironmentError,
336
+ GpuResidencyCache,
337
+ HANDLE_CUBE,
338
+ HANDLE_CYLINDER,
339
+ HANDLE_QUAD,
340
+ HANDLE_SPHERE,
341
+ HANDLE_TRIANGLE,
342
+ INLINE_PACK_LOADERS,
343
+ LoaderRegistry,
344
+ PACK_ARTIFACT_LOADERS,
345
+ PROCEDURAL_FLOATS_PER_VERTEX,
346
+ ShaderRegistry,
347
+ World,
348
+ _makeStubGPU,
349
+ afterEach,
350
+ animationClipLoader,
351
+ assetRegistryModule,
352
+ audioLoader,
353
+ beforeEach,
354
+ buildSceneChildContext,
355
+ createBoxGeometry,
356
+ createDevImportTransport,
357
+ createEngineMetrics,
358
+ createPlaneGeometry,
359
+ createRuntimeRenderer,
360
+ defineComponent,
361
+ deriveBuiltin,
362
+ describe,
363
+ expect,
364
+ expectTypeOf,
365
+ fileURLToPath,
366
+ fontLoader,
367
+ getOrCreateMipmapPipeline,
368
+ it,
369
+ makeFakeRhiDevice,
370
+ makeMockCanvas,
371
+ makeMockShaderRegistry,
372
+ materialLoader,
373
+ meshFromInterleaved,
374
+ meshLoader,
375
+ mipmapCacheSize,
376
+ numMipLevels,
377
+ ok,
378
+ readFileSync,
379
+ requireRenderer,
380
+ resolveAssetHandle,
381
+ rhi,
382
+ rhiOk,
383
+ sceneLoader,
384
+ skeletonLoader,
385
+ skinLoader,
386
+ spies,
387
+ textureLoader,
388
+ toShared,
389
+ toUnique,
390
+ unwrapHandle,
391
+ vi,
392
+ walkMaterialPassesOverSharedRefs,
393
+ wireDefaultLoaders,
394
+ ];
395
+ type __MergedKeep =
396
+ | EquirectAsset
397
+ | Handle
398
+ | ImportTransport
399
+ | MaterialAsset
400
+ | MaterialPass
401
+ | SamplerAsset;
402
+
403
+ {
404
+ // --- from parse-scene-payload-refs.test.ts ---
405
+ /** Access the private parseAssetPayload method via structural view-cast. */
406
+ function accessParseScenePayload(reg: AssetRegistry) {
407
+ // biome-ignore lint/suspicious/noExplicitAny: private method access for unit test
408
+ const internal = reg as any as {
409
+ parseAssetPayload(kind: string, payload: Record<string, unknown>, refs?: string[]): unknown;
410
+ };
411
+ return (
412
+ kind: string,
413
+ payload: Record<string, unknown>,
414
+ refs?: string[],
415
+ ): SceneAsset | undefined => {
416
+ const result = internal.parseAssetPayload(kind, payload, refs);
417
+ if (result === undefined) return undefined;
418
+ if (
419
+ typeof result === 'object' &&
420
+ result !== null &&
421
+ 'kind' in result &&
422
+ result.kind === 'scene'
423
+ ) {
424
+ return result as SceneAsset;
425
+ }
426
+ return undefined;
427
+ };
428
+ }
429
+
430
+ const GUID_A = 'cbe42beb-8975-5096-b3a1-3dda4cb4c077';
431
+ const GUID_B = 'f6af7007-158f-4d92-9e47-93bf2f213e1f';
432
+
433
+ describe('w1 - parseScenePayload refs normal paths (AC-01)', () => {
434
+ it('replaces number field values with refs[N] GUID string', () => {
435
+ const reg = new AssetRegistry(makeMockShaderRegistry());
436
+ const fn = accessParseScenePayload(reg);
437
+ const refs = [GUID_A, GUID_B];
438
+ const payload = {
439
+ entities: [
440
+ {
441
+ localId: 0,
442
+ components: {
443
+ MeshFilter: { assetHandle: 0 },
444
+ MeshRenderer: { materials: [1] },
445
+ },
446
+ },
447
+ ],
448
+ };
449
+ const asset = fn('scene', payload, refs);
450
+ expect(asset).toBeDefined();
451
+ if (!asset) return;
452
+ expect(asset.kind).toBe('scene');
453
+ expect(asset.entities.length).toBe(1);
454
+ const comp = asset.entities[0]?.components as Record<string, Record<string, unknown>>;
455
+ expect(comp.MeshFilter?.assetHandle).toBe(GUID_A); // refs[0]
456
+ expect(comp.MeshRenderer?.materials).toEqual([GUID_B]); // refs[1]
457
+ });
458
+
459
+ it('replaces refs index 0 (valid zero-index)', () => {
460
+ const reg = new AssetRegistry(makeMockShaderRegistry());
461
+ const fn = accessParseScenePayload(reg);
462
+ const refs = [GUID_A];
463
+ const payload = {
464
+ entities: [
465
+ {
466
+ localId: 0,
467
+ components: { MeshFilter: { assetHandle: 0 } },
468
+ },
469
+ ],
470
+ };
471
+ const asset = fn('scene', payload, refs);
472
+ expect(asset).toBeDefined();
473
+ if (!asset) return;
474
+ const comp = asset.entities[0]?.components as Record<string, Record<string, unknown>>;
475
+ expect(comp.MeshFilter?.assetHandle).toBe(GUID_A);
476
+ });
477
+
478
+ it('keeps non-integer number fields unchanged (float values are not refs indices)', () => {
479
+ const reg = new AssetRegistry(makeMockShaderRegistry());
480
+ const fn = accessParseScenePayload(reg);
481
+ const refs = [GUID_A];
482
+ const payload = {
483
+ entities: [
484
+ {
485
+ localId: 0,
486
+ components: {
487
+ Transform: { pos: [1.5, 2.7, -3.2] },
488
+ DirectionalLight: { color: 'white', intensity: 0.8 },
489
+ },
490
+ },
491
+ ],
492
+ };
493
+ const asset = fn('scene', payload, refs);
494
+ expect(asset).toBeDefined();
495
+ if (!asset) return;
496
+ const comp = asset.entities[0]?.components as Record<string, Record<string, unknown>>;
497
+ // Non-integer float values are not refs indices — passed through unchanged.
498
+ expect(comp.Transform?.pos).toEqual([1.5, 2.7, -3.2]);
499
+ expect(comp.DirectionalLight?.color).toBe('white');
500
+ expect(comp.DirectionalLight?.intensity).toBe(0.8);
501
+ });
502
+
503
+ it('keeps non-handle integer fields unchanged (Transform posX=0, ChildOf.parent=0)', () => {
504
+ const reg = new AssetRegistry(makeMockShaderRegistry());
505
+ const fn = accessParseScenePayload(reg);
506
+ const refs = [GUID_A];
507
+ const payload = {
508
+ entities: [
509
+ {
510
+ localId: 0,
511
+ components: {
512
+ ChildOf: { parent: 0 },
513
+ Transform: { pos: [0, 0, 0], quat: [0, 0, 0, 1], scale: [1, 1, 1] },
514
+ MeshFilter: { assetHandle: 0 },
515
+ },
516
+ },
517
+ ],
518
+ };
519
+ const asset = fn('scene', payload, refs);
520
+ expect(asset).toBeDefined();
521
+ if (!asset) return;
522
+ const comp = asset.entities[0]?.components as Record<string, Record<string, unknown>>;
523
+ // Non-handle integer fields are kept as-is (M1-fixup F-1)
524
+ expect(comp.ChildOf?.parent).toBe(0);
525
+ expect(comp.Transform?.pos).toEqual([0, 0, 0]);
526
+ expect(comp.Transform?.quat).toEqual([0, 0, 0, 1]);
527
+ expect(comp.Transform?.scale).toEqual([1, 1, 1]);
528
+ // Handle fields are replaced with GUID strings
529
+ expect(comp.MeshFilter?.assetHandle).toBe(GUID_A);
530
+ });
531
+
532
+ it('multiple nodes all resolve refs correctly', () => {
533
+ const reg = new AssetRegistry(makeMockShaderRegistry());
534
+ const fn = accessParseScenePayload(reg);
535
+ const refs = [GUID_A, GUID_B];
536
+ const payload = {
537
+ entities: [
538
+ {
539
+ localId: 0,
540
+ components: { MeshFilter: { assetHandle: 0 } },
541
+ },
542
+ {
543
+ localId: 1,
544
+ components: { MeshFilter: { assetHandle: 1 } },
545
+ },
546
+ {
547
+ localId: 2,
548
+ components: { MeshRenderer: { materials: [0] } },
549
+ },
550
+ ],
551
+ };
552
+ const asset = fn('scene', payload, refs);
553
+ expect(asset).toBeDefined();
554
+ if (!asset) return;
555
+ expect(asset.entities.length).toBe(3);
556
+ const comp0 = asset.entities[0]?.components as Record<string, Record<string, unknown>>;
557
+ const comp1 = asset.entities[1]?.components as Record<string, Record<string, unknown>>;
558
+ const comp2 = asset.entities[2]?.components as Record<string, Record<string, unknown>>;
559
+ expect(comp0.MeshFilter?.assetHandle).toBe(GUID_A);
560
+ expect(comp1.MeshFilter?.assetHandle).toBe(GUID_B);
561
+ expect(comp2.MeshRenderer?.materials).toEqual([GUID_A]);
562
+ });
563
+ });
564
+
565
+ describe('w2 - parseScenePayload refs error paths (AC-02, AC-08)', () => {
566
+ it('returns undefined when refs index is out of bounds (N >= refs.length)', () => {
567
+ const reg = new AssetRegistry(makeMockShaderRegistry());
568
+ const fn = accessParseScenePayload(reg);
569
+ const refs = [GUID_A]; // length=1, valid indices: 0 only
570
+ const payload = {
571
+ entities: [
572
+ {
573
+ localId: 0,
574
+ components: { MeshFilter: { assetHandle: 1 } }, // N=1 >= refs.length
575
+ },
576
+ ],
577
+ };
578
+ const result = fn('scene', payload, refs);
579
+ expect(result).toBeUndefined();
580
+ });
581
+
582
+ it('returns undefined when refs is empty and handle field references index 0', () => {
583
+ const reg = new AssetRegistry(makeMockShaderRegistry());
584
+ const fn = accessParseScenePayload(reg);
585
+ const refs: string[] = [];
586
+ const payload = {
587
+ entities: [
588
+ {
589
+ localId: 0,
590
+ components: { MeshFilter: { assetHandle: 0 } }, // N=0 >= refs.length (0 >= 0)
591
+ },
592
+ ],
593
+ };
594
+ const result = fn('scene', payload, refs);
595
+ expect(result).toBeUndefined();
596
+ });
597
+
598
+ it('stops on first error (AC-08): only first out-of-bounds node triggers failure', () => {
599
+ const reg = new AssetRegistry(makeMockShaderRegistry());
600
+ const fn = accessParseScenePayload(reg);
601
+ const refs = [GUID_A]; // length=1
602
+ const payload = {
603
+ entities: [
604
+ {
605
+ localId: 0,
606
+ components: { MeshFilter: { assetHandle: 1 } }, // first node: out of bounds
607
+ },
608
+ {
609
+ localId: 1,
610
+ components: { MeshFilter: { assetHandle: 0 } }, // second node: valid, but should not be reached
611
+ },
612
+ ],
613
+ };
614
+ // parseScenePayload returns undefined on first error, so result is undefined
615
+ // regardless of the second node's validity
616
+ const result = fn('scene', payload, refs);
617
+ expect(result).toBeUndefined();
618
+ });
619
+
620
+ it('returns undefined when index is negative', () => {
621
+ const reg = new AssetRegistry(makeMockShaderRegistry());
622
+ const fn = accessParseScenePayload(reg);
623
+ const refs = [GUID_A];
624
+ const payload = {
625
+ entities: [
626
+ {
627
+ localId: 0,
628
+ components: { MeshFilter: { assetHandle: -1 } },
629
+ },
630
+ ],
631
+ };
632
+ const result = fn('scene', payload, refs);
633
+ expect(result).toBeUndefined();
634
+ });
635
+
636
+ it('backward compat: parseScenePayload without refs returns SceneAsset with numbers unchanged', () => {
637
+ const reg = new AssetRegistry(makeMockShaderRegistry());
638
+ const fn = accessParseScenePayload(reg);
639
+ const payload = {
640
+ entities: [
641
+ {
642
+ localId: 0,
643
+ components: {
644
+ MeshFilter: { assetHandle: 42 },
645
+ MeshRenderer: { materials: [1024] },
646
+ },
647
+ },
648
+ ],
649
+ };
650
+ // No refs passed -- old call signature, numbers should pass through
651
+ const asset = fn('scene', payload);
652
+ expect(asset).toBeDefined();
653
+ if (!asset) return;
654
+ const comp = asset.entities[0]?.components as Record<string, Record<string, unknown>>;
655
+ expect(comp.MeshFilter?.assetHandle).toBe(42);
656
+ expect(comp.MeshRenderer?.materials).toEqual([1024]);
657
+ });
658
+
659
+ it('ignores all integer fields without refs and keeps them as-is (non-handle integers)', () => {
660
+ const reg = new AssetRegistry(makeMockShaderRegistry());
661
+ const fn = accessParseScenePayload(reg);
662
+ const refs = [GUID_A];
663
+ const payload = {
664
+ entities: [
665
+ {
666
+ localId: 0,
667
+ components: { Transform: { pos: [0, 0, 0], quat: [0, 0, 0, 1], scale: [1, 1, 1] } },
668
+ },
669
+ ],
670
+ };
671
+ const asset = fn('scene', payload, refs);
672
+ expect(asset).toBeDefined();
673
+ if (!asset) return;
674
+ const comp = asset.entities[0]?.components as Record<string, Record<string, unknown>>;
675
+ // M1-fixup F-1: non-handle integer fields (Transform) are preserved as-is.
676
+ // Only fields in the HANDLE_FIELD_NAMES allowlist get refs resolution.
677
+ expect(comp.Transform?.pos).toEqual([0, 0, 0]);
678
+ expect(comp.Transform?.quat).toEqual([0, 0, 0, 1]);
679
+ expect(comp.Transform?.scale).toEqual([1, 1, 1]);
680
+ });
681
+ });
682
+
683
+ describe('w2 - fetchPackFile wrapping produces AssetError for failed parse', () => {
684
+ it('loadByGuid returns asset-parse-failed when scene refs index is out of bounds', async () => {
685
+ const reg = new AssetRegistry(makeMockShaderRegistry());
686
+ const guid = AssetGuid.parse('00000000-0000-7000-8000-000000000099');
687
+ if (!guid.ok) throw new Error('expected ok');
688
+
689
+ // Register a pack file with a scene containing out-of-bounds refs.
690
+ // parseAssetPayload returns { ok: false, error }, then fetchPackFile
691
+ // wraps it as asset-parse-failed.
692
+ const badPayload = {
693
+ entities: [
694
+ {
695
+ localId: 0,
696
+ components: { MeshFilter: { assetHandle: 5 } }, // refs length is 3, 5 is out of bounds
697
+ },
698
+ ],
699
+ };
700
+ const packEntry = {
701
+ guid: '00000000-0000-7000-8000-000000000099',
702
+ kind: 'scene',
703
+ payload: badPayload,
704
+ refs: [
705
+ 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee',
706
+ '11111111-2222-3333-4444-555555555555',
707
+ 'ffffffff-gggg-hhhh-iiii-jjjjjjjjjjjj',
708
+ ],
709
+ };
710
+
711
+ // registerWithGuid wraps the raw pack entry lookup — loadByGuid dev path
712
+ // directly hits the guid->handle map without fetchPackFile. We verify
713
+ // the parse failure through the parseAssetPayload structural access
714
+ // (the fetchPackFile path is an integration concern for smoke tests).
715
+ // For unit test: use loadByGuid's dev path which registers a
716
+ // scene asset directly. When we call parseAssetPayload with the
717
+ // bad refs, it returns undefined, which would become asset-parse-failed
718
+ // through fetchPackFile.
719
+ // biome-ignore lint/suspicious/noExplicitAny: private method access
720
+ const internal = reg as any as {
721
+ parseAssetPayload(kind: string, payload: Record<string, unknown>, refs?: string[]): unknown;
722
+ };
723
+ // F21: scene refs out-of-bounds returns the structured error inline via
724
+ // the LoaderOutput { ok: false, error } arm (no instance-slot side effect).
725
+ const result = internal.parseAssetPayload('scene', badPayload, packEntry.refs) as {
726
+ ok: false;
727
+ error: { index: number; refsLength: number };
728
+ };
729
+ expect(result.ok).toBe(false);
730
+ expect(result.error.index).toBe(5);
731
+ });
732
+
733
+ it('parseScenePayload returns structured ParseSceneError on refs out-of-bounds (F-2 / AC-02)', () => {
734
+ const reg = new AssetRegistry(makeMockShaderRegistry());
735
+ // biome-ignore lint/suspicious/noExplicitAny: private method access
736
+ const internal = reg as any;
737
+ const badPayload = {
738
+ entities: [
739
+ {
740
+ localId: 42,
741
+ components: { MeshFilter: { assetHandle: 5 } },
742
+ },
743
+ ],
744
+ };
745
+ const refs = ['guid-a', 'guid-b']; // length=2, 5 is out of bounds
746
+ // F21: the structured error is the return value's `error` field, not a
747
+ // shared instance slot.
748
+ const result = internal.parseAssetPayload('scene', badPayload, refs) as {
749
+ ok: false;
750
+ error: {
751
+ localId: number;
752
+ component: string;
753
+ field: string;
754
+ index: number;
755
+ refsLength: number;
756
+ };
757
+ };
758
+ expect(result.ok).toBe(false);
759
+ const err = result.error;
760
+ expect(err.localId).toBe(42);
761
+ expect(err.component).toBe('MeshFilter');
762
+ expect(err.field).toBe('assetHandle');
763
+ expect(err.index).toBe(5);
764
+ expect(err.refsLength).toBe(2);
765
+ });
766
+ });
767
+ }