@carbonenginejs/runtime-resource 0.9.2 → 0.11.0

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 (544) hide show
  1. package/NOTICE +3 -2
  2. package/README.md +47 -6
  3. package/dist/CjsMotherLode.js +88 -88
  4. package/dist/CjsMotherLode.js.map +1 -1
  5. package/dist/CjsResMan.js +717 -228
  6. package/dist/CjsResMan.js.map +1 -1
  7. package/dist/CjsResManFetchProvider.js +94 -0
  8. package/dist/CjsResManFetchProvider.js.map +1 -0
  9. package/dist/{CjsResManQueue.js → CjsResManWorkQueue.js} +112 -25
  10. package/dist/CjsResManWorkQueue.js.map +1 -0
  11. package/dist/format/CjsBlueReader.js +89 -0
  12. package/dist/format/CjsBlueReader.js.map +1 -1
  13. package/dist/format/CjsFormat.js +42 -16
  14. package/dist/format/CjsFormat.js.map +1 -1
  15. package/dist/format/CjsReader.js +4 -0
  16. package/dist/format/CjsReader.js.map +1 -1
  17. package/dist/format/CjsResourceProbe.js +2 -0
  18. package/dist/format/CjsResourceProbe.js.map +1 -1
  19. package/dist/format/effect/effectPermutationGraph.js +257 -0
  20. package/dist/format/effect/effectPermutationGraph.js.map +1 -0
  21. package/dist/format/effect/effectReflectionPackage.js +636 -0
  22. package/dist/format/effect/effectReflectionPackage.js.map +1 -0
  23. package/dist/format/effect/sha256.js +114 -0
  24. package/dist/format/effect/sha256.js.map +1 -0
  25. package/dist/format/payloadContract.js +20 -0
  26. package/dist/format/payloadContract.js.map +1 -1
  27. package/dist/formats/black/CjsBlackFormat.js +15 -1
  28. package/dist/formats/black/CjsBlackFormat.js.map +1 -1
  29. package/dist/formats/black/core/CjsBlackBinaryReader.js +103 -0
  30. package/dist/formats/black/core/CjsBlackBinaryReader.js.map +1 -1
  31. package/dist/formats/black/core/CjsBlackPropertyReaders.js +61 -0
  32. package/dist/formats/black/core/CjsBlackPropertyReaders.js.map +1 -1
  33. package/dist/formats/black/core/CjsBlackReader.js +125 -0
  34. package/dist/formats/black/core/CjsBlackReader.js.map +1 -1
  35. package/dist/formats/black/core/CjsBlackSchemaRegistry.js +103 -0
  36. package/dist/formats/black/core/CjsBlackSchemaRegistry.js.map +1 -1
  37. package/dist/formats/black/core/helpers.js +17 -0
  38. package/dist/formats/black/core/helpers.js.map +1 -1
  39. package/dist/formats/bnk/CjsBnkFormat.js +8 -0
  40. package/dist/formats/bnk/CjsBnkFormat.js.map +1 -1
  41. package/dist/formats/bnk/core/helpers.js +20 -0
  42. package/dist/formats/bnk/core/helpers.js.map +1 -1
  43. package/dist/formats/bnk/core/musicNodes.js +40 -3
  44. package/dist/formats/bnk/core/musicNodes.js.map +1 -1
  45. package/dist/formats/bnk/core/soundbanksInfo.js +2 -0
  46. package/dist/formats/bnk/core/soundbanksInfo.js.map +1 -1
  47. package/dist/formats/cmf/core/binary.js +71 -0
  48. package/dist/formats/cmf/core/binary.js.map +1 -1
  49. package/dist/formats/cmf/core/buffers.js +4 -0
  50. package/dist/formats/cmf/core/buffers.js.map +1 -1
  51. package/dist/formats/cmf/core/helpers.js +31 -0
  52. package/dist/formats/cmf/core/helpers.js.map +1 -1
  53. package/dist/formats/cmf/core/schema.js +10 -0
  54. package/dist/formats/cmf/core/schema.js.map +1 -1
  55. package/dist/formats/cmf/core/shared.js +9 -0
  56. package/dist/formats/cmf/core/shared.js.map +1 -1
  57. package/dist/formats/cmf/core/writer.js +54 -0
  58. package/dist/formats/cmf/core/writer.js.map +1 -1
  59. package/dist/formats/dds/core/bc6h.js +10 -0
  60. package/dist/formats/dds/core/bc6h.js.map +1 -1
  61. package/dist/formats/dds/core/bc7.js +16 -0
  62. package/dist/formats/dds/core/bc7.js.map +1 -1
  63. package/dist/formats/dds/core/helpers.js +47 -0
  64. package/dist/formats/dds/core/helpers.js.map +1 -1
  65. package/dist/formats/dxbc/CjsDxbcFormat.js +142 -0
  66. package/dist/formats/dxbc/CjsDxbcFormat.js.map +1 -0
  67. package/dist/formats/dxbc/core/DxbcReader.js +266 -0
  68. package/dist/formats/dxbc/core/DxbcReader.js.map +1 -0
  69. package/dist/formats/dxbc/core/container.js +169 -0
  70. package/dist/formats/dxbc/core/container.js.map +1 -0
  71. package/dist/formats/dxbc/core/decoder.js +789 -0
  72. package/dist/formats/dxbc/core/decoder.js.map +1 -0
  73. package/dist/formats/dxbc/core/errors.js +19 -0
  74. package/dist/formats/dxbc/core/errors.js.map +1 -0
  75. package/dist/formats/dxbc/core/helpers.js +220 -0
  76. package/dist/formats/dxbc/core/helpers.js.map +1 -0
  77. package/dist/formats/dxbc/core/opcodes.js +45 -0
  78. package/dist/formats/dxbc/core/opcodes.js.map +1 -0
  79. package/dist/formats/dxbc/core/program.js +91 -0
  80. package/dist/formats/dxbc/core/program.js.map +1 -0
  81. package/dist/formats/dxbc/core/signature.js +172 -0
  82. package/dist/formats/dxbc/core/signature.js.map +1 -0
  83. package/dist/formats/dxbc/index.js +2 -0
  84. package/dist/formats/dxbc/index.js.map +1 -0
  85. package/dist/formats/fbx/core/helpers.js +21 -0
  86. package/dist/formats/fbx/core/helpers.js.map +1 -1
  87. package/dist/formats/flac/CjsFlacFormat.js +49 -0
  88. package/dist/formats/flac/CjsFlacFormat.js.map +1 -1
  89. package/dist/formats/flac/core/helpers.js +20 -0
  90. package/dist/formats/flac/core/helpers.js.map +1 -1
  91. package/dist/formats/gif/CjsGifFormat.js +49 -0
  92. package/dist/formats/gif/CjsGifFormat.js.map +1 -1
  93. package/dist/formats/gif/core/helpers.js +20 -0
  94. package/dist/formats/gif/core/helpers.js.map +1 -1
  95. package/dist/formats/gltf/core/helpers.js +15 -0
  96. package/dist/formats/gltf/core/helpers.js.map +1 -1
  97. package/dist/formats/gltf/core/parser.js +13 -0
  98. package/dist/formats/gltf/core/parser.js.map +1 -1
  99. package/dist/formats/gltf/core/targets.js +10 -0
  100. package/dist/formats/gltf/core/targets.js.map +1 -1
  101. package/dist/formats/gr2/core/bitknit2.js +2 -0
  102. package/dist/formats/gr2/core/bitknit2.js.map +1 -1
  103. package/dist/formats/gr2/core/helpers.js +20 -0
  104. package/dist/formats/gr2/core/helpers.js.map +1 -1
  105. package/dist/formats/gr2/core/targets.js +10 -0
  106. package/dist/formats/gr2/core/targets.js.map +1 -1
  107. package/dist/formats/hlsl/CjsHlslFormat.js +254 -0
  108. package/dist/formats/hlsl/CjsHlslFormat.js.map +1 -0
  109. package/dist/formats/hlsl/core/HlslBinaryUtils.js +15 -0
  110. package/dist/formats/hlsl/core/HlslBinaryUtils.js.map +1 -0
  111. package/dist/formats/hlsl/core/HlslEffectReadError.js +19 -0
  112. package/dist/formats/hlsl/core/HlslEffectReadError.js.map +1 -0
  113. package/dist/formats/hlsl/core/HlslEffectStateManager.js +130 -0
  114. package/dist/formats/hlsl/core/HlslEffectStateManager.js.map +1 -0
  115. package/dist/formats/hlsl/core/HlslReader.js +266 -0
  116. package/dist/formats/hlsl/core/HlslReader.js.map +1 -0
  117. package/dist/formats/hlsl/core/HlslRenderStateSetup.js +37 -0
  118. package/dist/formats/hlsl/core/HlslRenderStateSetup.js.map +1 -0
  119. package/dist/formats/hlsl/core/HlslResourceSetDescription.js +94 -0
  120. package/dist/formats/hlsl/core/HlslResourceSetDescription.js.map +1 -0
  121. package/dist/formats/hlsl/core/HlslShaderBytecode.js +44 -0
  122. package/dist/formats/hlsl/core/HlslShaderBytecode.js.map +1 -0
  123. package/dist/formats/hlsl/core/analysis.js +51 -0
  124. package/dist/formats/hlsl/core/analysis.js.map +1 -0
  125. package/dist/formats/hlsl/core/helpers.js +270 -0
  126. package/dist/formats/hlsl/core/helpers.js.map +1 -0
  127. package/dist/formats/hlsl/core/json.js +284 -0
  128. package/dist/formats/hlsl/core/json.js.map +1 -0
  129. package/dist/formats/hlsl/core/metadata.js +327 -0
  130. package/dist/formats/hlsl/core/metadata.js.map +1 -0
  131. package/dist/formats/hlsl/core/portableReflection.js +848 -0
  132. package/dist/formats/hlsl/core/portableReflection.js.map +1 -0
  133. package/dist/formats/hlsl/core/render-states.js +280 -0
  134. package/dist/formats/hlsl/core/render-states.js.map +1 -0
  135. package/dist/formats/hlsl/core/tr2/HlslRenderContextEnum.js +43 -0
  136. package/dist/formats/hlsl/core/tr2/HlslRenderContextEnum.js.map +1 -0
  137. package/dist/formats/hlsl/core/tr2/resources/HlslEffectRes.js +294 -0
  138. package/dist/formats/hlsl/core/tr2/resources/HlslEffectRes.js.map +1 -0
  139. package/dist/formats/hlsl/core/tr2/resources/HlslShaderPermutation.js +33 -0
  140. package/dist/formats/hlsl/core/tr2/resources/HlslShaderPermutation.js.map +1 -0
  141. package/dist/formats/hlsl/core/tr2/shader/HlslEffectBindingManifest.js +416 -0
  142. package/dist/formats/hlsl/core/tr2/shader/HlslEffectBindingManifest.js.map +1 -0
  143. package/dist/formats/hlsl/core/tr2/shader/HlslEffectConstant.js +40 -0
  144. package/dist/formats/hlsl/core/tr2/shader/HlslEffectConstant.js.map +1 -0
  145. package/dist/formats/hlsl/core/tr2/shader/HlslEffectDescription.js +742 -0
  146. package/dist/formats/hlsl/core/tr2/shader/HlslEffectDescription.js.map +1 -0
  147. package/dist/formats/hlsl/core/tr2/shader/HlslEffectLibrary.js +52 -0
  148. package/dist/formats/hlsl/core/tr2/shader/HlslEffectLibrary.js.map +1 -0
  149. package/dist/formats/hlsl/core/tr2/shader/HlslEffectParameterAnnotation.js +38 -0
  150. package/dist/formats/hlsl/core/tr2/shader/HlslEffectParameterAnnotation.js.map +1 -0
  151. package/dist/formats/hlsl/core/tr2/shader/HlslEffectResource.js +50 -0
  152. package/dist/formats/hlsl/core/tr2/shader/HlslEffectResource.js.map +1 -0
  153. package/dist/formats/hlsl/core/tr2/shader/HlslEffectStageInput.js +86 -0
  154. package/dist/formats/hlsl/core/tr2/shader/HlslEffectStageInput.js.map +1 -0
  155. package/dist/formats/hlsl/core/tr2/shader/HlslEffectTechnique.js +31 -0
  156. package/dist/formats/hlsl/core/tr2/shader/HlslEffectTechnique.js.map +1 -0
  157. package/dist/formats/hlsl/core/tr2/shader/HlslPass.js +42 -0
  158. package/dist/formats/hlsl/core/tr2/shader/HlslPass.js.map +1 -0
  159. package/dist/formats/hlsl/core/tr2/shader/HlslSamplerDescription.js +55 -0
  160. package/dist/formats/hlsl/core/tr2/shader/HlslSamplerDescription.js.map +1 -0
  161. package/dist/formats/hlsl/core/tr2/shader/HlslSamplerSetup.js +29 -0
  162. package/dist/formats/hlsl/core/tr2/shader/HlslSamplerSetup.js.map +1 -0
  163. package/dist/formats/hlsl/core/tr2/shader/HlslShader.js +220 -0
  164. package/dist/formats/hlsl/core/tr2/shader/HlslShader.js.map +1 -0
  165. package/dist/formats/hlsl/core/tr2/shader/HlslShaderOption.js +30 -0
  166. package/dist/formats/hlsl/core/tr2/shader/HlslShaderOption.js.map +1 -0
  167. package/dist/formats/hlsl/index.js +2 -0
  168. package/dist/formats/hlsl/index.js.map +1 -0
  169. package/dist/formats/hlsl/portable.js +2 -0
  170. package/dist/formats/hlsl/portable.js.map +1 -0
  171. package/dist/formats/index.js +4 -0
  172. package/dist/formats/index.js.map +1 -1
  173. package/dist/formats/jpeg/core/helpers.js +52 -0
  174. package/dist/formats/jpeg/core/helpers.js.map +1 -1
  175. package/dist/formats/jpeg/core/jpeg.js +93 -0
  176. package/dist/formats/jpeg/core/jpeg.js.map +1 -1
  177. package/dist/formats/mp3/core/helpers.js +37 -0
  178. package/dist/formats/mp3/core/helpers.js.map +1 -1
  179. package/dist/formats/mp4/core/helpers.js +35 -0
  180. package/dist/formats/mp4/core/helpers.js.map +1 -1
  181. package/dist/formats/ogg/CjsOggFormat.js +49 -0
  182. package/dist/formats/ogg/CjsOggFormat.js.map +1 -1
  183. package/dist/formats/ogg/core/helpers.js +23 -0
  184. package/dist/formats/ogg/core/helpers.js.map +1 -1
  185. package/dist/formats/ogg/core/vorbis.js +13 -0
  186. package/dist/formats/ogg/core/vorbis.js.map +1 -1
  187. package/dist/formats/png/core/helpers.js +52 -0
  188. package/dist/formats/png/core/helpers.js.map +1 -1
  189. package/dist/formats/red/CjsRedFormat.js +2 -0
  190. package/dist/formats/red/CjsRedFormat.js.map +1 -1
  191. package/dist/formats/red/core/CjsRedReader.js +52 -0
  192. package/dist/formats/red/core/CjsRedReader.js.map +1 -1
  193. package/dist/formats/red/core/helpers.js +19 -0
  194. package/dist/formats/red/core/helpers.js.map +1 -1
  195. package/dist/formats/stl/core/stl.js +8 -0
  196. package/dist/formats/stl/core/stl.js.map +1 -1
  197. package/dist/formats/stl/core/targets.js +10 -0
  198. package/dist/formats/stl/core/targets.js.map +1 -1
  199. package/dist/formats/tga/core/helpers.js +47 -0
  200. package/dist/formats/tga/core/helpers.js.map +1 -1
  201. package/dist/formats/wav/core/helpers.js +37 -0
  202. package/dist/formats/wav/core/helpers.js.map +1 -1
  203. package/dist/formats/webgl/CjsWebglFormat.js +221 -0
  204. package/dist/formats/webgl/CjsWebglFormat.js.map +1 -0
  205. package/dist/formats/webgl/core/cewg/CewgPackage.js +339 -0
  206. package/dist/formats/webgl/core/cewg/CewgPackage.js.map +1 -0
  207. package/dist/formats/webgl/core/cewg/CewgPackageBuilder.js +104 -0
  208. package/dist/formats/webgl/core/cewg/CewgPackageBuilder.js.map +1 -0
  209. package/dist/formats/webgl/core/cewg/binary.js +101 -0
  210. package/dist/formats/webgl/core/cewg/binary.js.map +1 -0
  211. package/dist/formats/webgl/core/cewgCompleteness.js +81 -0
  212. package/dist/formats/webgl/core/cewgCompleteness.js.map +1 -0
  213. package/dist/formats/webgl/core/effectPackage.js +789 -0
  214. package/dist/formats/webgl/core/effectPackage.js.map +1 -0
  215. package/dist/formats/webgl/core/effectPackageValidation.js +331 -0
  216. package/dist/formats/webgl/core/effectPackageValidation.js.map +1 -0
  217. package/dist/formats/webgl/core/errors.js +27 -0
  218. package/dist/formats/webgl/core/errors.js.map +1 -0
  219. package/dist/formats/webgl/core/glsl/DxbcGlslEmitter.js +2678 -0
  220. package/dist/formats/webgl/core/glsl/DxbcGlslEmitter.js.map +1 -0
  221. package/dist/formats/webgl/core/glsl/DxbcGlslHelpers.js +89 -0
  222. package/dist/formats/webgl/core/glsl/DxbcGlslHelpers.js.map +1 -0
  223. package/dist/formats/webgl/core/glsl/DxbcGlslOperandFormatter.js +428 -0
  224. package/dist/formats/webgl/core/glsl/DxbcGlslOperandFormatter.js.map +1 -0
  225. package/dist/formats/webgl/core/helpers.js +306 -0
  226. package/dist/formats/webgl/core/helpers.js.map +1 -0
  227. package/dist/formats/webgl/index.js +2 -0
  228. package/dist/formats/webgl/index.js.map +1 -0
  229. package/dist/formats/webgpu/CjsWebgpuFormat.js +376 -0
  230. package/dist/formats/webgpu/CjsWebgpuFormat.js.map +1 -0
  231. package/dist/formats/webgpu/core/cewgpu/CewgpuPackage.js +415 -0
  232. package/dist/formats/webgpu/core/cewgpu/CewgpuPackage.js.map +1 -0
  233. package/dist/formats/webgpu/core/cewgpu/CewgpuPackageBuilder.js +100 -0
  234. package/dist/formats/webgpu/core/cewgpu/CewgpuPackageBuilder.js.map +1 -0
  235. package/dist/formats/webgpu/core/cewgpu/binary.js +93 -0
  236. package/dist/formats/webgpu/core/cewgpu/binary.js.map +1 -0
  237. package/dist/formats/webgpu/core/cewgpu/tags.js +17 -0
  238. package/dist/formats/webgpu/core/cewgpu/tags.js.map +1 -0
  239. package/dist/formats/webgpu/core/effectAnalysis.js +82 -0
  240. package/dist/formats/webgpu/core/effectAnalysis.js.map +1 -0
  241. package/dist/formats/webgpu/core/effectBackendBodySet.js +305 -0
  242. package/dist/formats/webgpu/core/effectBackendBodySet.js.map +1 -0
  243. package/dist/formats/webgpu/core/effectPackageValidation.js +1078 -0
  244. package/dist/formats/webgpu/core/effectPackageValidation.js.map +1 -0
  245. package/dist/formats/webgpu/core/errors.js +20 -0
  246. package/dist/formats/webgpu/core/errors.js.map +1 -0
  247. package/dist/formats/webgpu/core/helpers.js +448 -0
  248. package/dist/formats/webgpu/core/helpers.js.map +1 -0
  249. package/dist/formats/webgpu/core/ir/analyzeRegisterValues.js +223 -0
  250. package/dist/formats/webgpu/core/ir/analyzeRegisterValues.js.map +1 -0
  251. package/dist/formats/webgpu/core/ir/buildControlFlow.js +220 -0
  252. package/dist/formats/webgpu/core/ir/buildControlFlow.js.map +1 -0
  253. package/dist/formats/webgpu/core/ir/indexableTemps.js +137 -0
  254. package/dist/formats/webgpu/core/ir/indexableTemps.js.map +1 -0
  255. package/dist/formats/webgpu/core/ir/inferValueTypes.js +454 -0
  256. package/dist/formats/webgpu/core/ir/inferValueTypes.js.map +1 -0
  257. package/dist/formats/webgpu/core/ir/lowerDxbcToIr.js +494 -0
  258. package/dist/formats/webgpu/core/ir/lowerDxbcToIr.js.map +1 -0
  259. package/dist/formats/webgpu/core/ir/resolveRegisterFlow.js +177 -0
  260. package/dist/formats/webgpu/core/ir/resolveRegisterFlow.js.map +1 -0
  261. package/dist/formats/webgpu/core/ir/sourceLanes.js +61 -0
  262. package/dist/formats/webgpu/core/ir/sourceLanes.js.map +1 -0
  263. package/dist/formats/webgpu/core/packageEffect.js +300 -0
  264. package/dist/formats/webgpu/core/packageEffect.js.map +1 -0
  265. package/dist/formats/webgpu/core/packageEffectSelection.js +164 -0
  266. package/dist/formats/webgpu/core/packageEffectSelection.js.map +1 -0
  267. package/dist/formats/webgpu/core/packageMetadata.js +8 -0
  268. package/dist/formats/webgpu/core/packageMetadata.js.map +1 -0
  269. package/dist/formats/webgpu/core/schema.js +4 -0
  270. package/dist/formats/webgpu/core/schema.js.map +1 -0
  271. package/dist/formats/webgpu/core/wgsl/buildResourceTransformPlan.js +275 -0
  272. package/dist/formats/webgpu/core/wgsl/buildResourceTransformPlan.js.map +1 -0
  273. package/dist/formats/webgpu/core/wgsl/buildWgslBindingPlan.js +182 -0
  274. package/dist/formats/webgpu/core/wgsl/buildWgslBindingPlan.js.map +1 -0
  275. package/dist/formats/webgpu/core/wgsl/buildWgslSet.js +324 -0
  276. package/dist/formats/webgpu/core/wgsl/buildWgslSet.js.map +1 -0
  277. package/dist/formats/webgpu/core/wgsl/emitWgsl.js +356 -0
  278. package/dist/formats/webgpu/core/wgsl/emitWgsl.js.map +1 -0
  279. package/dist/formats/webgpu/core/wgsl/hoistEscapingValues.js +77 -0
  280. package/dist/formats/webgpu/core/wgsl/hoistEscapingValues.js.map +1 -0
  281. package/dist/formats/webgpu/core/wgsl/lowerBindingLayout.js +451 -0
  282. package/dist/formats/webgpu/core/wgsl/lowerBindingLayout.js.map +1 -0
  283. package/dist/formats/webgpu/core/wgsl/lowerComputeProgram.js +754 -0
  284. package/dist/formats/webgpu/core/wgsl/lowerComputeProgram.js.map +1 -0
  285. package/dist/formats/webgpu/core/wgsl/lowerCreateHistogramsComputeProgram.js +457 -0
  286. package/dist/formats/webgpu/core/wgsl/lowerCreateHistogramsComputeProgram.js.map +1 -0
  287. package/dist/formats/webgpu/core/wgsl/lowerFragmentProgram.js +1572 -0
  288. package/dist/formats/webgpu/core/wgsl/lowerFragmentProgram.js.map +1 -0
  289. package/dist/formats/webgpu/core/wgsl/lowerMergeHistogramsComputeProgram.js +659 -0
  290. package/dist/formats/webgpu/core/wgsl/lowerMergeHistogramsComputeProgram.js.map +1 -0
  291. package/dist/formats/webgpu/core/wgsl/lowerParticleClearComputePrograms.js +734 -0
  292. package/dist/formats/webgpu/core/wgsl/lowerParticleClearComputePrograms.js.map +1 -0
  293. package/dist/formats/webgpu/core/wgsl/lowerParticleEmitComputeProgram.js +583 -0
  294. package/dist/formats/webgpu/core/wgsl/lowerParticleEmitComputeProgram.js.map +1 -0
  295. package/dist/formats/webgpu/core/wgsl/lowerSkinVerticesComputeProgram.js +621 -0
  296. package/dist/formats/webgpu/core/wgsl/lowerSkinVerticesComputeProgram.js.map +1 -0
  297. package/dist/formats/webgpu/core/wgsl/lowerSortComputeProgram.js +824 -0
  298. package/dist/formats/webgpu/core/wgsl/lowerSortComputeProgram.js.map +1 -0
  299. package/dist/formats/webgpu/core/wgsl/lowerSortInnerComputeProgram.js +697 -0
  300. package/dist/formats/webgpu/core/wgsl/lowerSortInnerComputeProgram.js.map +1 -0
  301. package/dist/formats/webgpu/core/wgsl/lowerSortStepComputeProgram.js +559 -0
  302. package/dist/formats/webgpu/core/wgsl/lowerSortStepComputeProgram.js.map +1 -0
  303. package/dist/formats/webgpu/core/wgsl/lowerVertexProgram.js +1328 -0
  304. package/dist/formats/webgpu/core/wgsl/lowerVertexProgram.js.map +1 -0
  305. package/dist/formats/webgpu/core/wgsl/particleEmitSemanticDigest.js +110 -0
  306. package/dist/formats/webgpu/core/wgsl/particleEmitSemanticDigest.js.map +1 -0
  307. package/dist/formats/webgpu/core/wgsl/precisionControls.js +55 -0
  308. package/dist/formats/webgpu/core/wgsl/precisionControls.js.map +1 -0
  309. package/dist/formats/webgpu/core/wgsl/selectionPlans.js +758 -0
  310. package/dist/formats/webgpu/core/wgsl/selectionPlans.js.map +1 -0
  311. package/dist/formats/webgpu/core/wgsl/uniformity.js +78 -0
  312. package/dist/formats/webgpu/core/wgsl/uniformity.js.map +1 -0
  313. package/dist/formats/webgpu/core/wgsl/validateExactComputeIr.js +196 -0
  314. package/dist/formats/webgpu/core/wgsl/validateExactComputeIr.js.map +1 -0
  315. package/dist/formats/webgpu/core/wgsl/validateHandleOperand.js +37 -0
  316. package/dist/formats/webgpu/core/wgsl/validateHandleOperand.js.map +1 -0
  317. package/dist/formats/webgpu/index.js +2 -0
  318. package/dist/formats/webgpu/index.js.map +1 -0
  319. package/dist/formats/webm/core/helpers.js +35 -0
  320. package/dist/formats/webm/core/helpers.js.map +1 -1
  321. package/dist/formats/webp/CjsWebpFormat.js +49 -0
  322. package/dist/formats/webp/CjsWebpFormat.js.map +1 -1
  323. package/dist/formats/webp/core/helpers.js +23 -0
  324. package/dist/formats/webp/core/helpers.js.map +1 -1
  325. package/dist/formats/wem/CjsWemFormat.js +8 -0
  326. package/dist/formats/wem/CjsWemFormat.js.map +1 -1
  327. package/dist/formats/wem/core/bitStream.js +2 -0
  328. package/dist/formats/wem/core/bitStream.js.map +1 -1
  329. package/dist/formats/wem/core/helpers.js +20 -0
  330. package/dist/formats/wem/core/helpers.js.map +1 -1
  331. package/dist/formats/yaml/CjsYamlFormat.js +45 -0
  332. package/dist/formats/yaml/CjsYamlFormat.js.map +1 -1
  333. package/dist/formats/yaml/core/CjsYamlReader.js +91 -0
  334. package/dist/formats/yaml/core/CjsYamlReader.js.map +1 -1
  335. package/dist/formats/yaml/core/helpers.js +10 -0
  336. package/dist/formats/yaml/core/helpers.js.map +1 -1
  337. package/dist/index.js +56 -43
  338. package/dist/index.js.map +1 -1
  339. package/dist/{CjsResource.js → resource/CjsResource.js} +232 -17
  340. package/dist/resource/CjsResource.js.map +1 -0
  341. package/dist/{resources → resource}/Tr2LightProfileRes.js +4 -3
  342. package/dist/resource/Tr2LightProfileRes.js.map +1 -0
  343. package/dist/{resources → resource/audio}/AudioGeometryResData.js +1 -1
  344. package/dist/resource/audio/AudioGeometryResData.js.map +1 -0
  345. package/dist/resource/audio/CjsAudioBufferRes.js +86 -0
  346. package/dist/resource/audio/CjsAudioBufferRes.js.map +1 -0
  347. package/dist/resource/audio/CjsAudioRes.js +213 -0
  348. package/dist/resource/audio/CjsAudioRes.js.map +1 -0
  349. package/dist/resource/audio/index.js +4 -0
  350. package/dist/resource/audio/index.js.map +1 -0
  351. package/dist/{resources → resource/geometry}/MeshDecalData.js +1 -1
  352. package/dist/resource/geometry/MeshDecalData.js.map +1 -0
  353. package/dist/{resources → resource/geometry}/MeshDecalLodData.js +1 -1
  354. package/dist/resource/geometry/MeshDecalLodData.js.map +1 -0
  355. package/dist/resource/geometry/TriGeometryRes.js +656 -0
  356. package/dist/resource/geometry/TriGeometryRes.js.map +1 -0
  357. package/dist/{resources → resource/geometry}/TriGeometryResAreaData.js +1 -1
  358. package/dist/resource/geometry/TriGeometryResAreaData.js.map +1 -0
  359. package/dist/{resources → resource/geometry}/TriGeometryResJointData.js +1 -1
  360. package/dist/resource/geometry/TriGeometryResJointData.js.map +1 -0
  361. package/dist/{resources → resource/geometry}/TriGeometryResLodData.js +1 -1
  362. package/dist/resource/geometry/TriGeometryResLodData.js.map +1 -0
  363. package/dist/{resources → resource/geometry}/TriGeometryResMeshData.js +1 -1
  364. package/dist/resource/geometry/TriGeometryResMeshData.js.map +1 -0
  365. package/dist/{resources → resource/geometry}/TriGeometryResSkeletonData.js +1 -1
  366. package/dist/resource/geometry/TriGeometryResSkeletonData.js.map +1 -0
  367. package/dist/{resources → resource/geometry}/TriJointBinding.js +1 -1
  368. package/dist/resource/geometry/TriJointBinding.js.map +1 -0
  369. package/dist/{resources → resource/geometry}/TriMorphTargetGeometryConstants.js +1 -1
  370. package/dist/resource/geometry/TriMorphTargetGeometryConstants.js.map +1 -0
  371. package/dist/{resources → resource/geometry}/TriRtGeometryConstants.js +1 -1
  372. package/dist/resource/geometry/TriRtGeometryConstants.js.map +1 -0
  373. package/dist/{resources → resource/geometry/granny}/GStateBindingCallbackData.js +1 -1
  374. package/dist/resource/geometry/granny/GStateBindingCallbackData.js.map +1 -0
  375. package/dist/{resources → resource/geometry/granny}/Tr2GrannyIntersectionResult.js +1 -1
  376. package/dist/resource/geometry/granny/Tr2GrannyIntersectionResult.js.map +1 -0
  377. package/dist/{resources → resource/geometry/granny}/Tr2GrannyStateRes.js +6 -5
  378. package/dist/resource/geometry/granny/Tr2GrannyStateRes.js.map +1 -0
  379. package/dist/{resources → resource/geometry/granny}/TriGrannyRes.js +6 -5
  380. package/dist/resource/geometry/granny/TriGrannyRes.js.map +1 -0
  381. package/dist/{resources → resource/geometry/granny}/enums.js +1 -9
  382. package/dist/resource/geometry/granny/enums.js.map +1 -0
  383. package/dist/resource/geometry/granny/index.js +6 -0
  384. package/dist/resource/geometry/granny/index.js.map +1 -0
  385. package/dist/resource/geometry/index.js +17 -0
  386. package/dist/resource/geometry/index.js.map +1 -0
  387. package/dist/resource/index.js +52 -0
  388. package/dist/resource/index.js.map +1 -0
  389. package/dist/resource/resourceBoundary.js +64 -0
  390. package/dist/resource/resourceBoundary.js.map +1 -0
  391. package/dist/resource/shader/Tr2EffectRes.js +429 -0
  392. package/dist/resource/shader/Tr2EffectRes.js.map +1 -0
  393. package/dist/resource/shader/Tr2MaterialArea.js +34 -0
  394. package/dist/resource/shader/Tr2MaterialArea.js.map +1 -0
  395. package/dist/resource/shader/Tr2MaterialMesh.js +30 -0
  396. package/dist/resource/shader/Tr2MaterialMesh.js.map +1 -0
  397. package/dist/resource/shader/Tr2MaterialRes.js +35 -0
  398. package/dist/resource/shader/Tr2MaterialRes.js.map +1 -0
  399. package/dist/resource/shader/Tr2Shader.js +256 -0
  400. package/dist/resource/shader/Tr2Shader.js.map +1 -0
  401. package/dist/resource/shader/Tr2ShaderPermutation.js +47 -0
  402. package/dist/resource/shader/Tr2ShaderPermutation.js.map +1 -0
  403. package/dist/resource/shader/index.js +17 -0
  404. package/dist/resource/shader/index.js.map +1 -0
  405. package/dist/resource/shader/portable.js +33 -0
  406. package/dist/resource/shader/portable.js.map +1 -0
  407. package/dist/resource/shader/reflection/Tr2EffectConstant.js +135 -0
  408. package/dist/resource/shader/reflection/Tr2EffectConstant.js.map +1 -0
  409. package/dist/resource/shader/reflection/Tr2EffectDefine.js +28 -0
  410. package/dist/resource/shader/reflection/Tr2EffectDefine.js.map +1 -0
  411. package/dist/resource/shader/reflection/Tr2EffectDescription.js +107 -0
  412. package/dist/resource/shader/reflection/Tr2EffectDescription.js.map +1 -0
  413. package/dist/resource/shader/reflection/Tr2EffectLibrary.js +145 -0
  414. package/dist/resource/shader/reflection/Tr2EffectLibrary.js.map +1 -0
  415. package/dist/resource/shader/reflection/Tr2EffectParameterAnnotation.js +103 -0
  416. package/dist/resource/shader/reflection/Tr2EffectParameterAnnotation.js.map +1 -0
  417. package/dist/resource/shader/reflection/Tr2EffectResource.js +84 -0
  418. package/dist/resource/shader/reflection/Tr2EffectResource.js.map +1 -0
  419. package/dist/resource/shader/reflection/Tr2EffectStageInput.js +239 -0
  420. package/dist/resource/shader/reflection/Tr2EffectStageInput.js.map +1 -0
  421. package/dist/resource/shader/reflection/Tr2EffectTechnique.js +66 -0
  422. package/dist/resource/shader/reflection/Tr2EffectTechnique.js.map +1 -0
  423. package/dist/resource/shader/reflection/Tr2Pass.js +109 -0
  424. package/dist/resource/shader/reflection/Tr2Pass.js.map +1 -0
  425. package/dist/resource/shader/sampler/Tr2SamplerSetup.js +75 -0
  426. package/dist/resource/shader/sampler/Tr2SamplerSetup.js.map +1 -0
  427. package/dist/{texture → resource/texture}/CjsTextureArrayRes.js +83 -6
  428. package/dist/resource/texture/CjsTextureArrayRes.js.map +1 -0
  429. package/dist/{texture/CjsTextureParameterProxy.js → resource/texture/CjsTextureArrayResParameterProxy.js} +56 -10
  430. package/dist/resource/texture/CjsTextureArrayResParameterProxy.js.map +1 -0
  431. package/dist/{resources → resource/texture}/Tr2ImageRes.js +6 -4
  432. package/dist/resource/texture/Tr2ImageRes.js.map +1 -0
  433. package/dist/{resources → resource/texture}/Tr2TextureLodManager.js +3 -1
  434. package/dist/resource/texture/Tr2TextureLodManager.js.map +1 -0
  435. package/dist/{resources → resource/texture}/Tr2TextureLodUpdateRequest.js +1 -1
  436. package/dist/resource/texture/Tr2TextureLodUpdateRequest.js.map +1 -0
  437. package/dist/{resources → resource/texture}/Tr2TexturePackChannel.js +1 -1
  438. package/dist/resource/texture/Tr2TexturePackChannel.js.map +1 -0
  439. package/dist/{resources → resource/texture}/Tr2TexturePipeline.js +6 -4
  440. package/dist/resource/texture/Tr2TexturePipeline.js.map +1 -0
  441. package/dist/{resources → resource/texture}/Tr2TexturePipelineParams.js +1 -1
  442. package/dist/resource/texture/Tr2TexturePipelineParams.js.map +1 -0
  443. package/dist/{resources → resource/texture}/Tr2TexturePipelineStepCompress.js +1 -1
  444. package/dist/resource/texture/Tr2TexturePipelineStepCompress.js.map +1 -0
  445. package/dist/{resources → resource/texture}/Tr2TexturePipelineStepGenerateMips.js +1 -1
  446. package/dist/resource/texture/Tr2TexturePipelineStepGenerateMips.js.map +1 -0
  447. package/dist/{resources → resource/texture}/Tr2TexturePipelineStepLimitSize.js +1 -1
  448. package/dist/resource/texture/Tr2TexturePipelineStepLimitSize.js.map +1 -0
  449. package/dist/{resources → resource/texture}/Tr2TexturePipelineStepLoad.js +1 -1
  450. package/dist/resource/texture/Tr2TexturePipelineStepLoad.js.map +1 -0
  451. package/dist/{resources → resource/texture}/Tr2TexturePipelineStepPack.js +1 -1
  452. package/dist/resource/texture/Tr2TexturePipelineStepPack.js.map +1 -0
  453. package/dist/{resources → resource/texture}/TriTextureRes.js +42 -26
  454. package/dist/resource/texture/TriTextureRes.js.map +1 -0
  455. package/dist/resource/texture/index.js +15 -0
  456. package/dist/resource/texture/index.js.map +1 -0
  457. package/dist/{resources → resource/texture}/texturePipelineBehavior.js +59 -59
  458. package/dist/resource/texture/texturePipelineBehavior.js.map +1 -0
  459. package/dist/worker/CjsResManMainThreadLoader.js +87 -0
  460. package/dist/worker/CjsResManMainThreadLoader.js.map +1 -0
  461. package/dist/worker/CjsResManWorker.js +217 -0
  462. package/dist/worker/CjsResManWorker.js.map +1 -0
  463. package/dist/worker/CjsResManWorkerLoader.js +434 -0
  464. package/dist/worker/CjsResManWorkerLoader.js.map +1 -0
  465. package/dist/worker/protocol.js +12 -0
  466. package/dist/worker/protocol.js.map +1 -0
  467. package/docs/README.md +16 -3
  468. package/docs/architecture.md +39 -16
  469. package/docs/concepts/resource-lifecycle.md +2 -1
  470. package/docs/formats/README.md +8 -0
  471. package/docs/formats/provenance.md +11 -3
  472. package/docs/reference/classes/README.md +6 -4
  473. package/docs/reference/classes/audio.md +30 -0
  474. package/docs/reference/classes/core.md +31 -11
  475. package/docs/reference/classes/formats.md +440 -0
  476. package/docs/reference/classes/resources.md +151 -41
  477. package/docs/reference/classes/texture.md +7 -7
  478. package/docs/reference/motherlode-cache.md +17 -0
  479. package/docs/reference/queues.md +9 -1
  480. package/docs/reference/workers.md +135 -0
  481. package/docs/roadmap.md +27 -1
  482. package/format-notices/dxbc/LICENSE +21 -0
  483. package/format-notices/dxbc/NOTICE +20 -0
  484. package/format-notices/hlsl/LICENSE +21 -0
  485. package/format-notices/hlsl/NOTICE +25 -0
  486. package/format-notices/webgl/LICENSE +21 -0
  487. package/format-notices/webgl/NOTICE +35 -0
  488. package/format-notices/webgpu/LICENSE +21 -0
  489. package/format-notices/webgpu/NOTICE +31 -0
  490. package/package.json +13 -1
  491. package/dist/CjsResManQueue.js.map +0 -1
  492. package/dist/CjsResource.js.map +0 -1
  493. package/dist/CjsResourceSource.js +0 -68
  494. package/dist/CjsResourceSource.js.map +0 -1
  495. package/dist/resourcePath.js +0 -18
  496. package/dist/resourcePath.js.map +0 -1
  497. package/dist/resourceStates.js +0 -9
  498. package/dist/resourceStates.js.map +0 -1
  499. package/dist/resources/AudioGeometryResData.js.map +0 -1
  500. package/dist/resources/GStateBindingCallbackData.js.map +0 -1
  501. package/dist/resources/MeshDecalData.js.map +0 -1
  502. package/dist/resources/MeshDecalLodData.js.map +0 -1
  503. package/dist/resources/Tr2EffectRes.js +0 -71
  504. package/dist/resources/Tr2EffectRes.js.map +0 -1
  505. package/dist/resources/Tr2GrannyIntersectionResult.js.map +0 -1
  506. package/dist/resources/Tr2GrannyStateRes.js.map +0 -1
  507. package/dist/resources/Tr2ImageRes.js.map +0 -1
  508. package/dist/resources/Tr2LightProfileRes.js.map +0 -1
  509. package/dist/resources/Tr2MaterialArea.js +0 -34
  510. package/dist/resources/Tr2MaterialArea.js.map +0 -1
  511. package/dist/resources/Tr2MaterialMesh.js +0 -31
  512. package/dist/resources/Tr2MaterialMesh.js.map +0 -1
  513. package/dist/resources/Tr2MaterialRes.js +0 -34
  514. package/dist/resources/Tr2MaterialRes.js.map +0 -1
  515. package/dist/resources/Tr2ShaderPermutation.js +0 -43
  516. package/dist/resources/Tr2ShaderPermutation.js.map +0 -1
  517. package/dist/resources/Tr2TextureLodManager.js.map +0 -1
  518. package/dist/resources/Tr2TextureLodUpdateRequest.js.map +0 -1
  519. package/dist/resources/Tr2TexturePackChannel.js.map +0 -1
  520. package/dist/resources/Tr2TexturePipeline.js.map +0 -1
  521. package/dist/resources/Tr2TexturePipelineParams.js.map +0 -1
  522. package/dist/resources/Tr2TexturePipelineStepCompress.js.map +0 -1
  523. package/dist/resources/Tr2TexturePipelineStepGenerateMips.js.map +0 -1
  524. package/dist/resources/Tr2TexturePipelineStepLimitSize.js.map +0 -1
  525. package/dist/resources/Tr2TexturePipelineStepLoad.js.map +0 -1
  526. package/dist/resources/Tr2TexturePipelineStepPack.js.map +0 -1
  527. package/dist/resources/TriGeometryRes.js +0 -239
  528. package/dist/resources/TriGeometryRes.js.map +0 -1
  529. package/dist/resources/TriGeometryResAreaData.js.map +0 -1
  530. package/dist/resources/TriGeometryResJointData.js.map +0 -1
  531. package/dist/resources/TriGeometryResLodData.js.map +0 -1
  532. package/dist/resources/TriGeometryResMeshData.js.map +0 -1
  533. package/dist/resources/TriGeometryResSkeletonData.js.map +0 -1
  534. package/dist/resources/TriGrannyRes.js.map +0 -1
  535. package/dist/resources/TriJointBinding.js.map +0 -1
  536. package/dist/resources/TriMorphTargetGeometryConstants.js.map +0 -1
  537. package/dist/resources/TriRtGeometryConstants.js.map +0 -1
  538. package/dist/resources/TriTextureRes.js.map +0 -1
  539. package/dist/resources/enums.js.map +0 -1
  540. package/dist/resources/resourceBoundary.js +0 -47
  541. package/dist/resources/resourceBoundary.js.map +0 -1
  542. package/dist/resources/texturePipelineBehavior.js.map +0 -1
  543. package/dist/texture/CjsTextureArrayRes.js.map +0 -1
  544. package/dist/texture/CjsTextureParameterProxy.js.map +0 -1
package/dist/CjsResMan.js CHANGED
@@ -1,8 +1,11 @@
1
1
  import { CjsMotherLode, getMotherLodeKey } from './CjsMotherLode.js';
2
2
  import { CjsEventEmitter } from '@carbonenginejs/runtime-utils/model';
3
- import { CjsResource as _CjsResource } from './CjsResource.js';
4
- import { CjsResManWorkQueue, CjsResManQueue, NormalizeCjsResManQueue } from './CjsResManQueue.js';
5
- import { normalizeResourceExtension, normalizeResourcePath, getResourceExtension } from './resourcePath.js';
3
+ import { hasOwnThen } from '@carbonenginejs/runtime-utils/object';
4
+ import { normalizeResourcePath, normalizePath, normalizeResourceExtension, getResourceExtension } from '@carbonenginejs/runtime-utils/path';
5
+ import { CjsResource as _CjsResource } from './resource/CjsResource.js';
6
+ import { CjsResManWorkQueue, CjsResManQueue } from './CjsResManWorkQueue.js';
7
+ import { CjsResManMainThreadLoader } from './worker/CjsResManMainThreadLoader.js';
8
+ import { CjsResManWorkerLoader } from './worker/CjsResManWorkerLoader.js';
6
9
 
7
10
  /** @type {WeakMap<object, CjsResourceReadContext>} */
8
11
  const READ_CONTEXTS = new WeakMap();
@@ -30,6 +33,7 @@ let nextLocalValueIdentity = 1;
30
33
  * @property {CjsResMan} resMan Owning manager.
31
34
  * @property {object|Function} source Selected source implementation.
32
35
  * @property {string} path Normalized Carbon-style source path.
36
+ * @property {string} sourcePath Resource path or URL passed to the selected source.
33
37
  * @property {string|number|undefined} sourceRevision Caller content token.
34
38
  * @property {string} revisionKey Type-stable internal form of the content token.
35
39
  */
@@ -172,6 +176,8 @@ class CjsResMan extends CjsEventEmitter {
172
176
  super();
173
177
  this.motherLode = new CjsMotherLode();
174
178
  this.source = null;
179
+ this.paths = new Map();
180
+ this.pathResolver = null;
175
181
  this.resourceTypes = new Map();
176
182
  this.objectLoaders = new Map();
177
183
  this.formats = new Map();
@@ -179,11 +185,16 @@ class CjsResMan extends CjsEventEmitter {
179
185
  this.sourceOperations = new WeakMap();
180
186
  this.queuedSourceOperations = new WeakMap();
181
187
  this.formatOperations = new WeakMap();
188
+ this.mainThreadLoader = new CjsResManMainThreadLoader();
189
+ this.workerLoader = new CjsResManWorkerLoader({
190
+ fallback: this.mainThreadLoader
191
+ });
192
+ this.resourceLoader = this.workerLoader;
182
193
  this.maxConcurrentLoads = 8;
183
194
  this.maxPrepareTime = 0.005;
184
195
  this.maxPrepareItemsPerTick = 0;
185
196
  this.autoPumpMainThreadQueue = true;
186
- this.queueScheduler = DefaultQueueScheduler;
197
+ this.queueScheduler = defaultQueueScheduler;
187
198
  this.urgentResourceLoads = false;
188
199
  this._backgroundPumpScheduled = false;
189
200
  this._mainThreadPumpScheduled = false;
@@ -213,6 +224,11 @@ class CjsResMan extends CjsEventEmitter {
213
224
  * @param {object} [options={}] Additive source, registry, queue, format, and resource-type settings.
214
225
  * @param {number} [options.cacheSize] Recorded-byte budget immediately installed on the active MotherLode.
215
226
  * @param {object} [options.cacheCleanup] Cleanup policy used if a smaller configured budget evicts cached identities.
227
+ * @param {object} [options.mainThreadLoader] Direct execution strategy.
228
+ * @param {object|Map<string,string>} [options.paths] Resource-prefix URL bases.
229
+ * @param {Function|null} [options.pathResolver] Optional complete resource-path-to-URL resolver.
230
+ * @param {object} [options.workerLoader] Worker loader instance or construction options.
231
+ * @param {boolean} [options.useWorkerLoading=true] Whether worker-backed execution is selected.
216
232
  * @returns {CjsResMan} This resource manager.
217
233
  * @throws {TypeError} If options or any configured component are invalid.
218
234
  * @throws {Error|AggregateError} If resource mutations are active or replacing MotherLode cannot clean its resources.
@@ -221,60 +237,59 @@ class CjsResMan extends CjsEventEmitter {
221
237
  if (!options || typeof options !== "object" || Array.isArray(options)) {
222
238
  throw new TypeError("CjsResMan.Register options must be an object.");
223
239
  }
224
- if (Object.prototype.hasOwnProperty.call(options, "motherLode")) {
225
- const nextMotherLode = options.motherLode || new CjsMotherLode();
226
- if (nextMotherLode !== this.motherLode) {
227
- if (this.#activeResourceOperations > 0) {
228
- throw ActiveResourceOperationsError(this.#activeResourceOperations);
240
+ hasOwnThen(options, {
241
+ motherLode: value => {
242
+ const nextMotherLode = value || new CjsMotherLode();
243
+ if (nextMotherLode !== this.motherLode) {
244
+ if (this.#activeResourceOperations > 0) {
245
+ throw activeResourceOperationsError(this.#activeResourceOperations);
246
+ }
247
+ const previousMotherLode = this.motherLode;
248
+ this.#InvalidateMotherLodeOwnership(previousMotherLode);
249
+ previousMotherLode?.Shutdown?.();
250
+ this.motherLode = nextMotherLode;
251
+ this.motherLode.Startup?.();
252
+ this.#BindMotherLodeResources();
253
+ this.#reloadGenerations.clear();
254
+ this.#lastAutoPurgeTime = null;
229
255
  }
230
- const previousMotherLode = this.motherLode;
231
- this.#InvalidateMotherLodeOwnership(previousMotherLode);
232
- previousMotherLode?.Shutdown?.();
233
- this.motherLode = nextMotherLode;
234
- this.motherLode.Startup?.();
235
- this.#BindMotherLodeResources();
236
- this.#reloadGenerations.clear();
237
- this.#lastAutoPurgeTime = null;
238
- }
239
- }
240
- if (Object.prototype.hasOwnProperty.call(options, "cacheSize")) {
241
- this.motherLode.SetCacheSize(options.cacheSize, options.cacheCleanup || {});
242
- }
243
- if (Object.prototype.hasOwnProperty.call(options, "autoPurgePolicy")) {
244
- this.SetAutoPurgePolicy(options.autoPurgePolicy);
245
- }
246
- if (Object.prototype.hasOwnProperty.call(options, "source")) {
247
- this.SetSource(options.source);
248
- }
249
- if (Object.prototype.hasOwnProperty.call(options, "maxConcurrentLoads")) {
250
- AssertPositiveInteger(options.maxConcurrentLoads, "maxConcurrentLoads");
251
- this.maxConcurrentLoads = options.maxConcurrentLoads;
252
- this._loadQueue.SetConcurrency(this.maxConcurrentLoads);
253
- }
254
- if (Object.prototype.hasOwnProperty.call(options, "maxPrepareTime")) {
255
- AssertNonNegativeNumber(options.maxPrepareTime, "maxPrepareTime");
256
- this.maxPrepareTime = options.maxPrepareTime;
257
- }
258
- if (Object.prototype.hasOwnProperty.call(options, "maxPrepareItemsPerTick")) {
259
- AssertNonNegativeInteger(options.maxPrepareItemsPerTick, "maxPrepareItemsPerTick");
260
- this.maxPrepareItemsPerTick = options.maxPrepareItemsPerTick;
261
- }
262
- if (Object.prototype.hasOwnProperty.call(options, "autoPumpMainThreadQueue")) {
263
- this.autoPumpMainThreadQueue = Boolean(options.autoPumpMainThreadQueue);
264
- }
265
- if (Object.prototype.hasOwnProperty.call(options, "queueScheduler")) {
266
- if (options.queueScheduler !== null && typeof options.queueScheduler !== "function") {
267
- throw new TypeError("CjsResMan queueScheduler must be a function or null.");
268
- }
269
- this.queueScheduler = options.queueScheduler || DefaultQueueScheduler;
270
- }
271
- if (Object.prototype.hasOwnProperty.call(options, "urgentResourceLoads")) {
272
- this.SetUrgentResourceLoads(options.urgentResourceLoads);
273
- }
274
- for (const entry of NormalizeRegistrationEntries(options.formats)) {
256
+ },
257
+ cacheSize: value => this.motherLode.SetCacheSize(value, options.cacheCleanup || {}),
258
+ autoPurgePolicy: this.SetAutoPurgePolicy,
259
+ source: this.SetSource,
260
+ paths: this.SetPaths,
261
+ pathResolver: this.SetPathResolver,
262
+ mainThreadLoader: this.SetMainThreadLoader,
263
+ workerLoader: this.SetWorkerLoader,
264
+ useWorkerLoading: this.UseWorkerLoading,
265
+ maxConcurrentLoads: value => {
266
+ assertPositiveInteger(value, "maxConcurrentLoads");
267
+ this.maxConcurrentLoads = value;
268
+ this._loadQueue.SetConcurrency(value);
269
+ },
270
+ maxPrepareTime: value => {
271
+ assertNonNegativeNumber(value, "maxPrepareTime");
272
+ this.maxPrepareTime = value;
273
+ },
274
+ maxPrepareItemsPerTick: value => {
275
+ assertNonNegativeInteger(value, "maxPrepareItemsPerTick");
276
+ this.maxPrepareItemsPerTick = value;
277
+ },
278
+ autoPumpMainThreadQueue: value => {
279
+ this.autoPumpMainThreadQueue = Boolean(value);
280
+ },
281
+ queueScheduler: value => {
282
+ if (value !== null && typeof value !== "function") {
283
+ throw new TypeError("CjsResMan queueScheduler must be a function or null.");
284
+ }
285
+ this.queueScheduler = value || defaultQueueScheduler;
286
+ },
287
+ urgentResourceLoads: this.SetUrgentResourceLoads
288
+ }, this);
289
+ for (const entry of normalizeRegistrationEntries(options.formats)) {
275
290
  if (typeof entry === "function") this.RegisterFormat(entry);else this.RegisterFormat(entry.Format || entry.format, entry.defaults || {});
276
291
  }
277
- for (const entry of NormalizeRegistrationEntries(options.resourceTypes, true)) {
292
+ for (const entry of normalizeRegistrationEntries(options.resourceTypes, true)) {
278
293
  if (typeof entry === "function") this.RegisterResourceType(entry);else this.RegisterResourceType(entry.requirement || entry.payload || entry.key, entry.Constructor || entry.Resource || entry.resourceType, entry);
279
294
  }
280
295
  for (const [ext, loader] of Object.entries(options.objectLoaders || {})) {
@@ -295,6 +310,189 @@ class CjsResMan extends CjsEventEmitter {
295
310
  this.source = source || null;
296
311
  return this;
297
312
  }
313
+
314
+ /**
315
+ * Add or replace one resource-prefix URL base.
316
+ *
317
+ * @param {string} prefix Resource scheme without `:/`.
318
+ * @param {string} urlBase URL base ending at the scheme root.
319
+ * @returns {CjsResMan} This resource manager.
320
+ */
321
+ SetPath(prefix, urlBase) {
322
+ const key = normalizePathPrefix(prefix);
323
+ const value = normalizeUrlBase(urlBase);
324
+ this.paths.set(key, value);
325
+ return this;
326
+ }
327
+
328
+ /**
329
+ * Add or replace resource-prefix URL bases from an object or Map.
330
+ *
331
+ * @param {object|Map<string,string>} paths Prefix/base entries.
332
+ * @returns {CjsResMan} This resource manager.
333
+ */
334
+ SetPaths(paths) {
335
+ if (!paths || typeof paths !== "object" && !(paths instanceof Map) || Array.isArray(paths)) {
336
+ throw new TypeError("CjsResMan paths must be an object or Map.");
337
+ }
338
+ const entries = paths instanceof Map ? paths.entries() : Object.entries(paths);
339
+ for (const [prefix, urlBase] of entries) {
340
+ this.SetPath(prefix, urlBase);
341
+ }
342
+ return this;
343
+ }
344
+
345
+ /**
346
+ * Reports whether a resource-prefix URL base is registered.
347
+ *
348
+ * @param {string} prefix Resource scheme without `:/`.
349
+ * @returns {boolean}
350
+ */
351
+ HasPath(prefix) {
352
+ return this.paths.has(normalizePathPrefix(prefix));
353
+ }
354
+
355
+ /**
356
+ * Returns one registered resource-prefix URL base.
357
+ *
358
+ * @param {string} prefix Resource scheme without `:/`.
359
+ * @returns {string|null}
360
+ */
361
+ GetPath(prefix) {
362
+ return this.paths.get(normalizePathPrefix(prefix)) || null;
363
+ }
364
+
365
+ /**
366
+ * Replaces the complete resource-path-to-URL resolver.
367
+ *
368
+ * @param {Function|null} resolver Resolver called as `(resourcePath, resMan)`.
369
+ * @returns {CjsResMan} This resource manager.
370
+ */
371
+ SetPathResolver(resolver) {
372
+ if (resolver !== null && resolver !== undefined && typeof resolver !== "function") {
373
+ throw new TypeError("CjsResMan pathResolver must be a function or null.");
374
+ }
375
+ this.pathResolver = resolver || null;
376
+ return this;
377
+ }
378
+
379
+ /**
380
+ * Builds the URL used by URL-backed providers while preserving the resource
381
+ * path as the canonical resource identity.
382
+ *
383
+ * @param {string} path Resource path or direct HTTP(S) URL.
384
+ * @returns {string} Resolved URL.
385
+ */
386
+ BuildUrl(path) {
387
+ const normalized = normalizeResourcePath(path);
388
+ if (!normalized) {
389
+ throw new TypeError("CjsResMan resource path must be a non-empty string.");
390
+ }
391
+ if (this.pathResolver) {
392
+ return normalizeResolvedUrl(this.pathResolver(normalized, this));
393
+ }
394
+ const prefixIndex = normalized.indexOf(":/");
395
+ if (prefixIndex === -1) {
396
+ return normalizePath(path);
397
+ }
398
+ const prefix = normalized.slice(0, prefixIndex);
399
+ if (prefix === "http" || prefix === "https") {
400
+ return normalizePath(path);
401
+ }
402
+ const urlBase = this.paths.get(prefix);
403
+ if (!urlBase) {
404
+ const error = new Error(`CjsResMan resource path prefix is not registered: ${prefix}`);
405
+ error.code = "CJS_RESMAN_PATH_PREFIX_UNREGISTERED";
406
+ error.path = normalized;
407
+ error.prefix = prefix;
408
+ throw error;
409
+ }
410
+ return `${urlBase}${normalized.slice(prefixIndex + 2)}`;
411
+ }
412
+
413
+ /**
414
+ * Replace the direct execution strategy used by unsupported worker
415
+ * operations and whenever worker loading is not selected.
416
+ *
417
+ * @param {object} loader Loader exposing `Read` and `ReadFormat`.
418
+ * @returns {CjsResMan} This resource manager.
419
+ */
420
+ SetMainThreadLoader(loader) {
421
+ assertResourceLoader(loader, "mainThreadLoader");
422
+ const wasSelected = this.resourceLoader === this.mainThreadLoader;
423
+ this.mainThreadLoader = loader;
424
+ this.workerLoader?.SetFallback?.(loader);
425
+ if (wasSelected || !this.resourceLoader) this.resourceLoader = loader;
426
+ return this;
427
+ }
428
+
429
+ /**
430
+ * Install a worker loader instance or construct one from options.
431
+ *
432
+ * Installation does not select worker execution; call
433
+ * `UseWorkerLoading(true)` or pass `useWorkerLoading: true`.
434
+ *
435
+ * @param {object|null} loader Worker loader or CjsResManWorkerLoader options.
436
+ * @returns {CjsResMan} This resource manager.
437
+ */
438
+ SetWorkerLoader(loader) {
439
+ const wasSelected = this.resourceLoader === this.workerLoader;
440
+ if (loader === null || loader === false) {
441
+ this.workerLoader = null;
442
+ if (wasSelected) this.resourceLoader = this.mainThreadLoader;
443
+ return this;
444
+ }
445
+ const resolved = isResourceLoader(loader) ? loader : new CjsResManWorkerLoader({
446
+ ...(loader || {}),
447
+ fallback: loader?.fallback || this.mainThreadLoader
448
+ });
449
+ assertResourceLoader(resolved, "workerLoader");
450
+ this.workerLoader = resolved;
451
+ if (wasSelected) this.resourceLoader = resolved;
452
+ return this;
453
+ }
454
+
455
+ /**
456
+ * Select worker-backed execution, lazily creating the default module worker
457
+ * loader when required. Unsupported sources and formats still use the
458
+ * configured main-thread loader.
459
+ *
460
+ * @param {boolean} [value=true] Whether worker execution is selected.
461
+ * @returns {CjsResMan} This resource manager.
462
+ */
463
+ UseWorkerLoading(value = true) {
464
+ if (!value) {
465
+ this.resourceLoader = this.mainThreadLoader;
466
+ return this;
467
+ }
468
+ if (!this.workerLoader) this.SetWorkerLoader({});
469
+ this.workerLoader.Reset?.();
470
+ this.resourceLoader = this.workerLoader;
471
+ return this;
472
+ }
473
+
474
+ /**
475
+ * Report whether worker-backed execution is the selected strategy.
476
+ *
477
+ * @returns {boolean}
478
+ */
479
+ IsWorkerLoading() {
480
+ return Boolean(this.workerLoader && this.resourceLoader === this.workerLoader);
481
+ }
482
+
483
+ /**
484
+ * Return unresolved requests owned by the selected/installed worker loader.
485
+ *
486
+ * @returns {number}
487
+ */
488
+ GetPendingWorkers() {
489
+ return this.workerLoader?.GetPendingCount?.() || 0;
490
+ }
491
+
492
+ /**
493
+ * Enqueues a resource task on the selected execution lane for the resource
494
+ * manager.
495
+ */
298
496
  AddToQueue(queue, callback, context = null, flags = 0) {
299
497
  const task = this.QueueTask(queue, callback, context, {
300
498
  flags
@@ -304,12 +502,24 @@ class CjsResMan extends CjsEventEmitter {
304
502
  });
305
503
  return task.id;
306
504
  }
505
+
506
+ /** Cancels a queued resource task before it starts for the resource manager. */
307
507
  CancelFromQueue(queue, id, reason = "") {
308
508
  return this.GetWorkQueue(queue).Cancel(id, reason);
309
509
  }
510
+
511
+ /**
512
+ * Allocates the next task identifier for a selected queue for the resource
513
+ * manager.
514
+ */
310
515
  GetNextIdForQueue(queue) {
311
516
  return this.GetWorkQueue(queue).GetNextId();
312
517
  }
518
+
519
+ /**
520
+ * Starts pending preparation work within the main-thread concurrency limit for
521
+ * the resource manager.
522
+ */
313
523
  PumpMainThreadQueue(options = {}) {
314
524
  const urgent = options.urgent === true || this.urgentResourceLoads;
315
525
  const result = this._prepareQueue.Pump({
@@ -320,6 +530,11 @@ class CjsResMan extends CjsEventEmitter {
320
530
  if (result.queued > 0 && result.active === 0) this.ScheduleMainThreadQueue();
321
531
  return result.processed > 0;
322
532
  }
533
+
534
+ /**
535
+ * Starts pending load work within the background concurrency limit for the
536
+ * resource manager.
537
+ */
323
538
  PumpBackgroundQueue(options = {}) {
324
539
  const result = this._loadQueue.Pump({
325
540
  maxItems: options.maxItems ?? 0,
@@ -328,22 +543,47 @@ class CjsResMan extends CjsEventEmitter {
328
543
  });
329
544
  return result.processed > 0;
330
545
  }
546
+
547
+ /**
548
+ * Prevents the selected queue from starting additional work for the resource
549
+ * manager.
550
+ */
331
551
  PauseQueue(queue) {
332
552
  this.GetWorkQueue(queue).Pause();
333
553
  return this;
334
554
  }
555
+
556
+ /**
557
+ * Allows the selected queue to start pending work again for the resource
558
+ * manager.
559
+ */
335
560
  ResumeQueue(queue) {
336
- const name = NormalizeCjsResManQueue(queue);
561
+ const name = CjsResManWorkQueue.normalizeName(queue);
337
562
  this.GetWorkQueue(name).Resume();
338
563
  if (name === CjsResManQueue.MAIN) this.ScheduleMainThreadQueue();else this.ScheduleBackgroundQueue();
339
564
  return this;
340
565
  }
566
+
567
+ /**
568
+ * Returns the number of load tasks waiting or running for the resource
569
+ * manager.
570
+ */
341
571
  GetPendingLoads() {
342
572
  return this._loadQueue.GetPendingCount();
343
573
  }
574
+
575
+ /**
576
+ * Returns the number of preparation tasks waiting or running for the resource
577
+ * manager.
578
+ */
344
579
  GetPendingPrepares() {
345
580
  return this._prepareQueue.GetPendingCount();
346
581
  }
582
+
583
+ /**
584
+ * Returns queue counts and concurrency state for diagnostics for the resource
585
+ * manager.
586
+ */
347
587
  GetQueueStats(queue = null) {
348
588
  if (queue !== null && queue !== undefined) return this.GetWorkQueue(queue).GetStats();
349
589
  return Object.freeze({
@@ -351,15 +591,30 @@ class CjsResMan extends CjsEventEmitter {
351
591
  prepares: this._prepareQueue.GetStats()
352
592
  });
353
593
  }
594
+
595
+ /**
596
+ * Switches resource loading between normal and urgent concurrency policy for
597
+ * the resource manager.
598
+ */
354
599
  SetUrgentResourceLoads(value) {
355
600
  this.urgentResourceLoads = Boolean(value);
356
601
  return this;
357
602
  }
603
+
604
+ /**
605
+ * Reports whether urgent resource-load scheduling is active for the resource
606
+ * manager.
607
+ */
358
608
  IsUrgentResourceLoads() {
359
609
  return this.urgentResourceLoads;
360
610
  }
611
+
612
+ /**
613
+ * Reports whether any resource load or preparation remains pending for the
614
+ * resource manager.
615
+ */
361
616
  IsLoading() {
362
- return this.GetPendingLoads() + this.GetPendingPrepares() > 0;
617
+ return this.GetPendingLoads() + this.GetPendingPrepares() + this.GetPendingWorkers() > 0;
363
618
  }
364
619
 
365
620
  /**
@@ -443,7 +698,7 @@ class CjsResMan extends CjsEventEmitter {
443
698
  await fence;
444
699
  return this;
445
700
  }
446
- const yieldQueue = options.yield || DefaultQueueYield;
701
+ const yieldQueue = options.yield || defaultQueueYield;
447
702
  let settled = false;
448
703
  fence.then(() => {
449
704
  settled = true;
@@ -456,8 +711,13 @@ class CjsResMan extends CjsEventEmitter {
456
711
  await fence;
457
712
  return this;
458
713
  }
714
+
715
+ /**
716
+ * Returns the execution queue selected by its public lane name for the
717
+ * resource manager.
718
+ */
459
719
  GetWorkQueue(queue) {
460
- return NormalizeCjsResManQueue(queue) === CjsResManQueue.MAIN ? this._prepareQueue : this._loadQueue;
720
+ return CjsResManWorkQueue.normalizeName(queue) === CjsResManQueue.MAIN ? this._prepareQueue : this._loadQueue;
461
721
  }
462
722
 
463
723
  /**
@@ -477,6 +737,8 @@ class CjsResMan extends CjsEventEmitter {
477
737
  QueueTask(queue, callback, context = null, metadata = null) {
478
738
  return this.#TrackQueueTask(this.GetWorkQueue(queue).Add(callback, context, metadata));
479
739
  }
740
+
741
+ /** Requests a later background-queue scheduling pass for the resource manager. */
480
742
  ScheduleBackgroundQueue() {
481
743
  if (this._backgroundPumpScheduled || this._loadQueue.IsPaused()) return this;
482
744
  this._backgroundPumpScheduled = true;
@@ -486,6 +748,11 @@ class CjsResMan extends CjsEventEmitter {
486
748
  });
487
749
  return this;
488
750
  }
751
+
752
+ /**
753
+ * Requests a later main-thread preparation scheduling pass for the resource
754
+ * manager.
755
+ */
489
756
  ScheduleMainThreadQueue() {
490
757
  if (!this.autoPumpMainThreadQueue || this._mainThreadPumpScheduled || this._prepareQueue.IsPaused()) return this;
491
758
  this._mainThreadPumpScheduled = true;
@@ -520,14 +787,14 @@ class CjsResMan extends CjsEventEmitter {
520
787
  Constructor = requirement;
521
788
  requirement = options.requirement || options.payload || Constructor.payload;
522
789
  }
523
- const key = NormalizeRequirement(requirement);
790
+ const key = normalizeRequirement(requirement);
524
791
  if (!key) throw new TypeError("CjsResMan.RegisterResourceType requires a semantic requirement.");
525
792
  if (typeof Constructor !== "function") {
526
793
  throw new TypeError("CjsResMan.RegisterResourceType requires a constructor or factory.");
527
794
  }
528
795
  this.resourceTypes.set(key, Constructor);
529
796
  for (const alias of options.aliases || []) {
530
- const aliasKey = NormalizeRequirement(alias);
797
+ const aliasKey = normalizeRequirement(alias);
531
798
  if (aliasKey) this.resourceTypes.set(aliasKey, Constructor);
532
799
  }
533
800
  return this;
@@ -575,7 +842,7 @@ class CjsResMan extends CjsEventEmitter {
575
842
  }
576
843
  const descriptor = Object.freeze({
577
844
  Format,
578
- defaults: SnapshotFormatDefaults(defaults)
845
+ defaults: snapshotFormatDefaults(defaults)
579
846
  });
580
847
  for (const inputType of Format.inputTypes) {
581
848
  const key = normalizeResourceExtension(inputType);
@@ -635,12 +902,12 @@ class CjsResMan extends CjsEventEmitter {
635
902
  if (options.emit !== undefined) {
636
903
  const objectLoader = this.GetObjectLoader(ext);
637
904
  if (objectLoader) {
638
- throw CreateObjectLoaderOutputMissingError(ext, options.emit);
905
+ throw createObjectLoaderOutputMissingError(ext, options.emit);
639
906
  } else {
640
907
  const descriptors = this.GetFormatDescriptors(ext);
641
- const candidates = FilterFormatDescriptors(descriptors, options);
908
+ const candidates = filterFormatDescriptors(descriptors, options);
642
909
  if (descriptors.length > 0 && candidates.length === 0) {
643
- throw CreateFormatOutputMissingError(ext, options.emit, descriptors);
910
+ throw createFormatOutputMissingError(ext, options.emit, descriptors);
644
911
  }
645
912
  }
646
913
  }
@@ -663,7 +930,7 @@ class CjsResMan extends CjsEventEmitter {
663
930
  this.motherLode.KeepAlive?.(cacheKey);
664
931
  const expectedOwnership = this.#RequireResourceOwnership(existing, "reload-candidate:create");
665
932
  const generation = this.#nextResourceReloadGeneration++;
666
- const loaderOptions = Object.freeze(GetResourceLoaderOptions(options, options.source || this.source));
933
+ const loaderOptions = Object.freeze(getResourceLoaderOptions(options, options.source || this.source));
667
934
  const candidate = Object.freeze({
668
935
  reloadCandidate: true,
669
936
  generation,
@@ -682,7 +949,7 @@ class CjsResMan extends CjsEventEmitter {
682
949
  reload: true
683
950
  };
684
951
  resource.SetObjectLoader(loadOptions => this.#GetReloadCandidateObject(resource, {
685
- ...MergeResourceLoaderOptions(reloadOptions, loadOptions),
952
+ ...mergeResourceLoaderOptions(reloadOptions, loadOptions),
686
953
  reload: true
687
954
  }), reloadOptions);
688
955
  }
@@ -718,7 +985,7 @@ class CjsResMan extends CjsEventEmitter {
718
985
  */
719
986
  GetObject(path, options = {}) {
720
987
  const resource = this.GetResource(path, options);
721
- const operationOptions = MergeResourceLoaderOptions(resource.GetObjectRequest?.() || {}, options);
988
+ const operationOptions = mergeResourceLoaderOptions(resource.GetObjectRequest?.() || {}, options);
722
989
  if (this.#reloadCandidates.has(resource)) {
723
990
  return this.#GetReloadCandidateObject(resource, operationOptions);
724
991
  }
@@ -729,7 +996,7 @@ class CjsResMan extends CjsEventEmitter {
729
996
  }
730
997
  if (resource.HasPayload?.()) {
731
998
  resource.KeepPayloadAlive?.();
732
- return Promise.resolve(GetPublishedResourceObject(resource));
999
+ return Promise.resolve(getPublishedResourceObject(resource));
733
1000
  }
734
1001
  const promise = this.QueueResourceObject(resource, operationOptions);
735
1002
  const operation = {
@@ -748,9 +1015,19 @@ class CjsResMan extends CjsEventEmitter {
748
1015
  });
749
1016
  return promise;
750
1017
  }
1018
+
1019
+ /**
1020
+ * Loads and hydrates an object graph through the configured resource pipeline
1021
+ * for the resource manager.
1022
+ */
751
1023
  LoadObject(path, options = {}) {
752
1024
  return this.GetObject(path, options);
753
1025
  }
1026
+
1027
+ /**
1028
+ * Fetches and hydrates an object graph without retaining a resource handle for
1029
+ * the resource manager.
1030
+ */
754
1031
  FetchObject(path, options = {}) {
755
1032
  return this.GetObject(path, options);
756
1033
  }
@@ -830,7 +1107,7 @@ class CjsResMan extends CjsEventEmitter {
830
1107
  #GetReloadCandidateObject(resource, options) {
831
1108
  const candidate = this.#reloadCandidates.get(resource) || null;
832
1109
  if (!candidate) {
833
- return Promise.reject(ReloadCandidateUnavailableError(resource));
1110
+ return Promise.reject(reloadCandidateUnavailableError(resource));
834
1111
  }
835
1112
  const existing = this.#reloadOperations.get(resource);
836
1113
  if (existing?.candidate === candidate) return existing.promise;
@@ -863,7 +1140,7 @@ class CjsResMan extends CjsEventEmitter {
863
1140
  */
864
1141
  async #RunReloadCandidate(candidate, options) {
865
1142
  let committed = false;
866
- let releaseLock = Noop;
1143
+ let releaseLock = noop;
867
1144
  const finishOperation = this.#BeginResourceOperation(true);
868
1145
  try {
869
1146
  this.#AssertReloadCandidate(candidate, "reload:begin");
@@ -887,7 +1164,7 @@ class CjsResMan extends CjsEventEmitter {
887
1164
  commitGuard: () => this.#IsReloadCandidateCurrent(candidate)
888
1165
  });
889
1166
  if (!result.committed) {
890
- throw StaleReloadCandidateError(candidate, "reload:commit-compare");
1167
+ throw staleReloadCandidateError(candidate, "reload:commit-compare");
891
1168
  }
892
1169
  committed = true;
893
1170
  this.#FinalizeCommittedReload(candidate);
@@ -936,7 +1213,7 @@ class CjsResMan extends CjsEventEmitter {
936
1213
  const errors = [];
937
1214
  try {
938
1215
  if (typeof candidate.resource.SetObjectLoader === "function") {
939
- candidate.resource.SetObjectLoader(loadOptions => this.GetObject(candidate.resource.GetPath(), MergeResourceLoaderOptions(candidate.loaderOptions, loadOptions)), candidate.loaderOptions);
1216
+ candidate.resource.SetObjectLoader(loadOptions => this.GetObject(candidate.resource.GetPath(), mergeResourceLoaderOptions(candidate.loaderOptions, loadOptions)), candidate.loaderOptions);
940
1217
  }
941
1218
  } catch (error) {
942
1219
  errors.push(error);
@@ -1022,6 +1299,11 @@ class CjsResMan extends CjsEventEmitter {
1022
1299
  throw new AggregateError(errors, "CjsResMan reload candidate ownership cleanup failed.");
1023
1300
  }
1024
1301
  }
1302
+
1303
+ /**
1304
+ * Fetches raw source bytes through the configured resource source for the
1305
+ * resource manager.
1306
+ */
1025
1307
  Fetch(path, options = {}) {
1026
1308
  return options.resource === true || options.requirement !== undefined || options.payload !== undefined ? this.FetchResource(path, options) : this.FetchObject(path, options);
1027
1309
  }
@@ -1206,16 +1488,25 @@ class CjsResMan extends CjsEventEmitter {
1206
1488
  */
1207
1489
  async #PrepareResourceObjectQueued(resource, bytes, options, ownership) {
1208
1490
  let object = bytes;
1209
- this.#AssertOptionalResourceOwnership(ownership, "queue-stage:read:enqueue");
1210
- const readTask = this.QueueTask(CjsResManQueue.MAIN, () => {
1211
- this.#AssertOptionalResourceOwnership(ownership, "queue-stage:read:run");
1212
- return this.ReadResourceObjectPayload(resource, bytes, options);
1213
- }, resource, {
1214
- kind: "prepare",
1215
- stage: "read",
1216
- path: resource.GetPath()
1217
- });
1218
- const read = await readTask.promise;
1491
+ const resolved = this.#ResolveResourceObjectRead(resource, bytes, options);
1492
+ const formatOptions = resolved.descriptor ? createFormatReadOptions(resolved.descriptor, options) : null;
1493
+ const runInWorker = Boolean(resolved.descriptor && typeof this.resourceLoader?.CanReadFormat === "function" && this.resourceLoader.CanReadFormat(resolved.descriptor, formatOptions));
1494
+ let read;
1495
+ if (runInWorker) {
1496
+ this.#AssertOptionalResourceOwnership(ownership, "worker-stage:read:run");
1497
+ read = await this.#ReadResolvedResourceObjectPayload(resource, bytes, options, resolved);
1498
+ } else {
1499
+ this.#AssertOptionalResourceOwnership(ownership, "queue-stage:read:enqueue");
1500
+ const readTask = this.QueueTask(CjsResManQueue.MAIN, () => {
1501
+ this.#AssertOptionalResourceOwnership(ownership, "queue-stage:read:run");
1502
+ return this.#ReadResolvedResourceObjectPayload(resource, bytes, options, resolved);
1503
+ }, resource, {
1504
+ kind: "prepare",
1505
+ stage: "read",
1506
+ path: resource.GetPath()
1507
+ });
1508
+ read = await readTask.promise;
1509
+ }
1219
1510
  this.#AssertOptionalResourceOwnership(ownership, "queue-stage:read:settled");
1220
1511
  if (read !== undefined) object = read;
1221
1512
  this.#AssertOptionalResourceOwnership(ownership, "queue-stage:publish:enqueue");
@@ -1245,18 +1536,52 @@ class CjsResMan extends CjsEventEmitter {
1245
1536
  * @throws {Error|TypeError} If no registered reader matches or its read contract fails.
1246
1537
  */
1247
1538
  async ReadResourceObjectPayload(resource, bytes, options = {}) {
1539
+ return this.#ReadResolvedResourceObjectPayload(resource, bytes, options, this.#ResolveResourceObjectRead(resource, bytes, options));
1540
+ }
1541
+
1542
+ /**
1543
+ * Resolve the configured direct loader or format descriptor once so queue
1544
+ * selection and execution use the same registration snapshot.
1545
+ *
1546
+ * @param {CjsResource} resource Resource whose CPU outcome is requested.
1547
+ * @param {*} bytes Source input.
1548
+ * @param {object} options Requested output options.
1549
+ * @returns {{loader: Function|null, descriptor: object|null}} Resolved reader.
1550
+ */
1551
+ #ResolveResourceObjectRead(resource, bytes, options) {
1248
1552
  const explicitLoader = this.GetObjectLoader(resource.GetExt());
1249
1553
  if (explicitLoader) {
1250
1554
  if (options.emit !== undefined) {
1251
- throw CreateObjectLoaderOutputMissingError(resource.GetExt(), options.emit);
1555
+ throw createObjectLoaderOutputMissingError(resource.GetExt(), options.emit);
1252
1556
  }
1253
- return explicitLoader(bytes, CreatePrepareContext(this, resource, bytes, options, "read"));
1557
+ return {
1558
+ loader: explicitLoader,
1559
+ descriptor: null
1560
+ };
1254
1561
  }
1255
- const descriptor = this.ResolveFormatDescriptor(resource.GetExt(), {
1256
- ...options,
1257
- bytes
1258
- });
1259
- return this.ReadFormatOnce(resource, descriptor, bytes, options);
1562
+ return {
1563
+ loader: null,
1564
+ descriptor: this.ResolveFormatDescriptor(resource.GetExt(), {
1565
+ ...options,
1566
+ bytes
1567
+ })
1568
+ };
1569
+ }
1570
+
1571
+ /**
1572
+ * Execute one already-resolved reader through its direct or format path.
1573
+ *
1574
+ * @param {CjsResource} resource Resource whose CPU outcome is requested.
1575
+ * @param {*} bytes Source input.
1576
+ * @param {object} options Requested output options.
1577
+ * @param {{loader: Function|null, descriptor: object|null}} resolved Reader selection.
1578
+ * @returns {Promise<*>} Reader result.
1579
+ */
1580
+ #ReadResolvedResourceObjectPayload(resource, bytes, options, resolved) {
1581
+ if (resolved.loader) {
1582
+ return resolved.loader(bytes, createPrepareContext(this, resource, bytes, options, "read"));
1583
+ }
1584
+ return this.ReadFormatOnce(resource, resolved.descriptor, bytes, options);
1260
1585
  }
1261
1586
 
1262
1587
  /**
@@ -1323,9 +1648,19 @@ class CjsResMan extends CjsEventEmitter {
1323
1648
  resource.SetPayload?.(object, options);
1324
1649
  resource.object = object;
1325
1650
  }
1326
- if (!resource.IsPrepared?.()) resource.MarkLoaded();
1651
+ // PREPARED, not LOADED: `object` is the reader/converter OUTCOME, so the
1652
+ // bytes have already been turned into whatever they needed to become.
1653
+ // LOADED means raw source data is in hand and still has to be prepared - a
1654
+ // resource in that state is not yet good, and marking it here left IsGood()
1655
+ // permanently false for every resource that does not prepare itself.
1656
+ if (!resource.IsPrepared?.()) resource.MarkPrepared();
1327
1657
  return result;
1328
1658
  }
1659
+
1660
+ /**
1661
+ * Warms a resource and its discovered dependencies without returning payload
1662
+ * data for the resource manager.
1663
+ */
1329
1664
  async Prefetch(paths, options = {}) {
1330
1665
  const entries = Array.isArray(paths) ? paths : [paths];
1331
1666
  return Promise.all(entries.map(path => this.LoadObject(path, options)));
@@ -1364,11 +1699,11 @@ class CjsResMan extends CjsEventEmitter {
1364
1699
  ResolveFormatDescriptor(inputType, options = {}) {
1365
1700
  const key = normalizeResourceExtension(inputType);
1366
1701
  const descriptors = this.GetFormatDescriptors(key);
1367
- const candidates = FilterFormatDescriptors(descriptors, options);
1702
+ const candidates = filterFormatDescriptors(descriptors, options);
1368
1703
  if (descriptors.length > 0 && candidates.length === 0 && options.emit !== undefined) {
1369
- throw CreateFormatOutputMissingError(key, options.emit, descriptors);
1704
+ throw createFormatOutputMissingError(key, options.emit, descriptors);
1370
1705
  }
1371
- return ResolveFormatDescriptorCandidates(candidates, key, options);
1706
+ return resolveFormatDescriptorCandidates(candidates, key, options);
1372
1707
  }
1373
1708
 
1374
1709
  /**
@@ -1383,32 +1718,7 @@ class CjsResMan extends CjsEventEmitter {
1383
1718
  * @throws {TypeError|Error} If the facade lacks a reader or reading fails.
1384
1719
  */
1385
1720
  async ReadFormat(descriptor, bytes, options = {}) {
1386
- const {
1387
- Format,
1388
- defaults
1389
- } = descriptor;
1390
- const formatOptions = {
1391
- ...defaults,
1392
- ...(options.formatOptions || {})
1393
- };
1394
- if (options.emit !== undefined) {
1395
- formatOptions.emit = FindDeclaredOutput(GetFormatOutputs(Format), options.emit) ?? options.emit;
1396
- }
1397
- if (options.classes !== undefined) formatOptions.classes = options.classes;
1398
- if (typeof Format.readAsync === "function") {
1399
- return Format.readAsync(bytes, formatOptions);
1400
- }
1401
- if (typeof Format.read === "function") {
1402
- return Format.read(bytes, formatOptions);
1403
- }
1404
- const reader = new Format(formatOptions);
1405
- if (typeof reader.ReadAsync === "function") {
1406
- return reader.ReadAsync(bytes, formatOptions);
1407
- }
1408
- if (typeof reader.Read === "function") {
1409
- return reader.Read(bytes, formatOptions);
1410
- }
1411
- throw new TypeError(`${Format.name} does not expose a read operation.`);
1721
+ return this.resourceLoader.ReadFormat(descriptor, bytes, createFormatReadOptions(descriptor, options));
1412
1722
  }
1413
1723
 
1414
1724
  /**
@@ -1502,7 +1812,7 @@ class CjsResMan extends CjsEventEmitter {
1502
1812
  * @throws {TypeError} If the policy, threshold, cleanup control, or clock is invalid.
1503
1813
  */
1504
1814
  SetAutoPurgePolicy(policy = null) {
1505
- this.#autoPurgePolicy = NormalizeAutoPurgePolicy(policy);
1815
+ this.#autoPurgePolicy = normalizeAutoPurgePolicy(policy);
1506
1816
  this.#lastAutoPurgeTime = null;
1507
1817
  return this;
1508
1818
  }
@@ -1539,11 +1849,11 @@ class CjsResMan extends CjsEventEmitter {
1539
1849
  * @throws {AggregateError} If a due sweep cannot clean one or more inactive resources.
1540
1850
  */
1541
1851
  PumpAutoPurge(options = {}) {
1542
- const pump = NormalizeAutoPurgePumpOptions(options);
1852
+ const pump = normalizeAutoPurgePumpOptions(options);
1543
1853
  const policy = this.#autoPurgePolicy;
1544
1854
  if (!policy) return null;
1545
1855
  const time = pump.time === undefined ? policy.now() : pump.time;
1546
- AssertNonNegativeNumber(time, "automatic purge time");
1856
+ assertNonNegativeNumber(time, "automatic purge time");
1547
1857
  if (this.#lastAutoPurgeTime !== null) {
1548
1858
  if (time < this.#lastAutoPurgeTime) {
1549
1859
  this.#lastAutoPurgeTime = time;
@@ -1608,8 +1918,8 @@ class CjsResMan extends CjsEventEmitter {
1608
1918
  throw new TypeError("CjsResMan.InvalidateReadCache options must be an object.");
1609
1919
  }
1610
1920
  const normalizedPath = normalizeResourcePath(path);
1611
- const hasRevision = Object.prototype.hasOwnProperty.call(options, "sourceRevision");
1612
- const revisionKey = hasRevision ? NormalizeSourceRevision(options.sourceRevision) : null;
1921
+ const hasRevision = hasOwn(options, "sourceRevision");
1922
+ const revisionKey = hasRevision ? normalizeSourceRevision(options.sourceRevision) : null;
1613
1923
  const source = options.source || this.source;
1614
1924
  if (!source) {
1615
1925
  return Object.freeze({
@@ -1670,9 +1980,9 @@ class CjsResMan extends CjsEventEmitter {
1670
1980
  throw new TypeError("CjsResMan requires a source with Read(path, options) to load objects.");
1671
1981
  }
1672
1982
  const sourceRevision = options.sourceRevision;
1673
- const revisionKey = NormalizeSourceRevision(sourceRevision);
1674
- NormalizeCachePolicy(options.cacheSource, "cacheSource");
1675
- NormalizeCachePolicy(options.cacheFormat, "cacheFormat");
1983
+ const revisionKey = normalizeSourceRevision(sourceRevision);
1984
+ normalizeCachePolicy(options.cacheSource, "cacheSource");
1985
+ normalizeCachePolicy(options.cacheFormat, "cacheFormat");
1676
1986
  const operationOptions = {
1677
1987
  ...options
1678
1988
  };
@@ -1680,6 +1990,7 @@ class CjsResMan extends CjsEventEmitter {
1680
1990
  resMan: this,
1681
1991
  source,
1682
1992
  path: normalizedPath,
1993
+ sourcePath: sourceRequiresUrl(source) ? this.BuildUrl(normalizedPath) : normalizedPath,
1683
1994
  sourceRevision,
1684
1995
  revisionKey
1685
1996
  });
@@ -1702,15 +2013,15 @@ class CjsResMan extends CjsEventEmitter {
1702
2013
  * @returns {Promise<*>} Promise for source bytes/data.
1703
2014
  */
1704
2015
  #QueueReadResource(context, options) {
1705
- const cachePolicy = NormalizeCachePolicy(options.cacheSource, "cacheSource");
1706
- const operations = GetOwnerOperations(this.queuedSourceOperations, context.source, true);
1707
- const key = GetReadOperationKey(context);
2016
+ const cachePolicy = normalizeCachePolicy(options.cacheSource, "cacheSource");
2017
+ const operations = getOwnerOperations(this.queuedSourceOperations, context.source, true);
2018
+ const key = getReadOperationKey(context);
1708
2019
  const bypassExisting = options.reload === true || cachePolicy === false;
1709
2020
  const existing = bypassExisting ? null : operations.get(key);
1710
2021
  if (existing) {
1711
2022
  if (cachePolicy === true) {
1712
2023
  existing.retain = true;
1713
- const sourceRecord = GetOwnerOperations(this.sourceOperations, context.source, false)?.get(key);
2024
+ const sourceRecord = getOwnerOperations(this.sourceOperations, context.source, false)?.get(key);
1714
2025
  if (sourceRecord) sourceRecord.retain = true;
1715
2026
  }
1716
2027
  return existing.promise;
@@ -1747,9 +2058,9 @@ class CjsResMan extends CjsEventEmitter {
1747
2058
  * @returns {Promise<*>} Promise for source bytes/data.
1748
2059
  */
1749
2060
  #ReadResource(context, options, queuedRecord = null) {
1750
- const cachePolicy = NormalizeCachePolicy(options.cacheSource, "cacheSource");
1751
- const operations = GetOwnerOperations(this.sourceOperations, context.source, true);
1752
- const key = GetReadOperationKey(context);
2061
+ const cachePolicy = normalizeCachePolicy(options.cacheSource, "cacheSource");
2062
+ const operations = getOwnerOperations(this.sourceOperations, context.source, true);
2063
+ const key = getReadOperationKey(context);
1753
2064
  const bypassExisting = options.reload === true || cachePolicy === false;
1754
2065
  const existing = bypassExisting ? null : operations.get(key);
1755
2066
  if (existing) {
@@ -1764,7 +2075,10 @@ class CjsResMan extends CjsEventEmitter {
1764
2075
  revisionKey: context.revisionKey,
1765
2076
  retain: cachePolicy === true || queuedRecord?.retain === true
1766
2077
  };
1767
- record.promise = Promise.resolve().then(() => context.source.Read(context.path, options));
2078
+ record.promise = Promise.resolve().then(() => this.resourceLoader.Read(context.source, context.sourcePath, {
2079
+ ...options,
2080
+ resourcePath: context.path
2081
+ }));
1768
2082
  if (cachePolicy !== false) operations.set(key, record);
1769
2083
  record.promise.then(() => {
1770
2084
  if (cachePolicy !== false && !record.retain && operations.get(key) === record) {
@@ -1785,8 +2099,8 @@ class CjsResMan extends CjsEventEmitter {
1785
2099
  * @returns {void}
1786
2100
  */
1787
2101
  #RetainSourceResult(context, value) {
1788
- const operations = GetOwnerOperations(this.sourceOperations, context.source, true);
1789
- const key = GetReadOperationKey(context);
2102
+ const operations = getOwnerOperations(this.sourceOperations, context.source, true);
2103
+ const key = getReadOperationKey(context);
1790
2104
  const existing = operations.get(key);
1791
2105
  if (existing) {
1792
2106
  existing.retain = true;
@@ -1810,13 +2124,13 @@ class CjsResMan extends CjsEventEmitter {
1810
2124
  * @returns {Readonly<{path: string, queuedSource: number, source: number, format: number}>} Frozen detached counts.
1811
2125
  */
1812
2126
  #InvalidateReadCache(source, path, revisionKey) {
1813
- const queuedSource = RemoveOperationRecords(GetOwnerOperations(this.queuedSourceOperations, source, false), path, revisionKey);
1814
- const sourceCount = RemoveOperationRecords(GetOwnerOperations(this.sourceOperations, source, false), path, revisionKey);
2127
+ const queuedSource = removeOperationRecords(getOwnerOperations(this.queuedSourceOperations, source, false), path, revisionKey);
2128
+ const sourceCount = removeOperationRecords(getOwnerOperations(this.sourceOperations, source, false), path, revisionKey);
1815
2129
  let format = 0;
1816
2130
  const descriptors = this.formatOperations.get(source);
1817
2131
  if (descriptors) {
1818
2132
  for (const [descriptor, operations] of descriptors) {
1819
- format += RemoveOperationRecords(operations, path, revisionKey);
2133
+ format += removeOperationRecords(operations, path, revisionKey);
1820
2134
  if (operations.size === 0) descriptors.delete(descriptor);
1821
2135
  }
1822
2136
  if (descriptors.size === 0) this.formatOperations.delete(source);
@@ -1847,12 +2161,12 @@ class CjsResMan extends CjsEventEmitter {
1847
2161
  throw new TypeError("Resource constructor must create a CjsResource-compatible object.");
1848
2162
  }
1849
2163
  if (disallowedAlias && resource === disallowedAlias) {
1850
- throw ReloadCandidateAliasError(path, resource);
2164
+ throw reloadCandidateAliasError(path, resource);
1851
2165
  }
1852
- resource.Initialize(path, ext, NormalizeRequirement(options.requirement || options.payload || ""));
2166
+ resource.Initialize(path, ext, normalizeRequirement(options.requirement || options.payload || ""));
1853
2167
  if (typeof resource.SetObjectLoader === "function") {
1854
- const loaderOptions = GetResourceLoaderOptions(options, options.source || this.source);
1855
- resource.SetObjectLoader(loadOptions => this.GetObject(path, MergeResourceLoaderOptions(loaderOptions, loadOptions)), loaderOptions);
2168
+ const loaderOptions = getResourceLoaderOptions(options, options.source || this.source);
2169
+ resource.SetObjectLoader(loadOptions => this.GetObject(path, mergeResourceLoaderOptions(loaderOptions, loadOptions)), loaderOptions);
1856
2170
  }
1857
2171
  return resource;
1858
2172
  }
@@ -1866,9 +2180,9 @@ class CjsResMan extends CjsEventEmitter {
1866
2180
  * @returns {Function} Registered resource constructor or `CjsResource`.
1867
2181
  */
1868
2182
  ResolveResourceConstructor(options = {}) {
1869
- const requested = NormalizeRequirement(options.requirement || options.payload);
2183
+ const requested = normalizeRequirement(options.requirement || options.payload);
1870
2184
  if (requested && this.resourceTypes.has(requested)) return this.resourceTypes.get(requested);
1871
- const emitted = NormalizeRequirement(options.emit);
2185
+ const emitted = normalizeRequirement(options.emit);
1872
2186
  if (emitted && this.resourceTypes.has(emitted)) return this.resourceTypes.get(emitted);
1873
2187
  return _CjsResource;
1874
2188
  }
@@ -1889,13 +2203,13 @@ class CjsResMan extends CjsEventEmitter {
1889
2203
  if (!options || typeof options !== "object" || Array.isArray(options)) {
1890
2204
  throw new TypeError("CjsResMan resource variant options must be an object.");
1891
2205
  }
1892
- if (Object.prototype.hasOwnProperty.call(options, "variant") && options.variant !== undefined) {
2206
+ if (hasOwn(options, "variant") && options.variant !== undefined) {
1893
2207
  if (typeof options.variant !== "string" || options.variant.trim() === "") {
1894
2208
  throw new TypeError("CjsResMan explicit resource variant must be a non-empty string.");
1895
2209
  }
1896
- return NormalizeResourceVariant(options.variant);
2210
+ return normalizeResourceVariant(options.variant);
1897
2211
  }
1898
- return NormalizeResourceVariant(options.emit ?? options.requirement ?? options.payload ?? "");
2212
+ return normalizeResourceVariant(options.emit ?? options.requirement ?? options.payload ?? "");
1899
2213
  }
1900
2214
 
1901
2215
  /**
@@ -1931,7 +2245,7 @@ class CjsResMan extends CjsEventEmitter {
1931
2245
  #BeginResourceOperation(queued) {
1932
2246
  this.#activeResourceOperations += 1;
1933
2247
  const id = queued ? this.#nextResourceOperationId++ : 0;
1934
- let resolveDone = Noop;
2248
+ let resolveDone = noop;
1935
2249
  const done = queued ? new Promise(resolve => {
1936
2250
  resolveDone = resolve;
1937
2251
  }) : null;
@@ -1976,7 +2290,7 @@ class CjsResMan extends CjsEventEmitter {
1976
2290
  #RequireResourceOwnership(resource, phase) {
1977
2291
  const ownership = this.#GetResourceOwnership(resource, phase);
1978
2292
  if (ownership) return ownership;
1979
- throw ResourceNotOwnedError(resource, phase);
2293
+ throw resourceNotOwnedError(resource, phase);
1980
2294
  }
1981
2295
 
1982
2296
  /**
@@ -2005,7 +2319,7 @@ class CjsResMan extends CjsEventEmitter {
2005
2319
  */
2006
2320
  #AssertResourceOwnership(ownership, phase) {
2007
2321
  if (!this.#IsResourceOwnershipCurrent(ownership)) {
2008
- throw StaleResourceOperationError(ownership, phase);
2322
+ throw staleResourceOperationError(ownership, phase);
2009
2323
  }
2010
2324
  }
2011
2325
 
@@ -2052,7 +2366,7 @@ class CjsResMan extends CjsEventEmitter {
2052
2366
  */
2053
2367
  #AssertReloadCandidate(candidate, phase) {
2054
2368
  if (!this.#IsReloadCandidateCurrent(candidate)) {
2055
- throw StaleReloadCandidateError(candidate, phase);
2369
+ throw staleReloadCandidateError(candidate, phase);
2056
2370
  }
2057
2371
  }
2058
2372
 
@@ -2099,7 +2413,7 @@ class CjsResMan extends CjsEventEmitter {
2099
2413
  key
2100
2414
  } = ownership;
2101
2415
  if (typeof owner?.Lock !== "function" || typeof owner?.Unlock !== "function") {
2102
- return Noop;
2416
+ return noop;
2103
2417
  }
2104
2418
  this.#AssertResourceOwnership(ownership, "lock:acquire");
2105
2419
  owner.Lock(key);
@@ -2120,6 +2434,67 @@ class CjsResMan extends CjsEventEmitter {
2120
2434
  * @param {object|Function} resource Canonical resource handle.
2121
2435
  * @returns {object|Function} The supplied resource.
2122
2436
  */
2437
+ /**
2438
+ * Reload a purged handle back into itself.
2439
+ *
2440
+ * Purge deletes the payload and drops the registry entry, so a consumer left
2441
+ * holding the handle has no way to reach a replacement - it cannot discover
2442
+ * one, and nothing hands it over. Recovery therefore has to fill THIS handle
2443
+ * rather than resolve whatever the manager currently caches for the path.
2444
+ *
2445
+ * The handle is re-registered BEFORE loading, so the ordinary load path finds
2446
+ * it as the canonical identity and loads into it instead of minting another.
2447
+ *
2448
+ * Declines rather than guesses in two cases: when another resource has since
2449
+ * claimed the identity - displacing it would kill whoever holds that one, the
2450
+ * very failure being fixed here - and when the retained request no longer
2451
+ * resolves to the same identity, which would re-register the handle under the
2452
+ * wrong key.
2453
+ *
2454
+ * @param {string} key Canonical resolved identity key.
2455
+ * @param {CjsResource} resource The purged handle to restore.
2456
+ * @returns {boolean} Whether a reload was started.
2457
+ */
2458
+ #ReloadPurgedResource(key, resource) {
2459
+ if (!resource?.IsPurged?.()) return false;
2460
+ try {
2461
+ const current = this.motherLode.Lookup(key);
2462
+ if (current && current !== resource) return false;
2463
+ const request = resource.GetObjectRequest?.() || {};
2464
+ const path = normalizeResourcePath(resource.GetPath());
2465
+ if (getMotherLodeKey(path, this.GetResourceVariant(request)) !== key) return false;
2466
+
2467
+ // Leave PURGED first: ownership is not considered current while purged,
2468
+ // so binding before this would produce a controller that no-ops.
2469
+ resource.MarkRequested();
2470
+ if (!current) this.motherLode.Insert(key, resource, {
2471
+ replace: true
2472
+ });
2473
+ this.#invalidResourceOwnership.delete(resource);
2474
+ this.#BindResourceLifecycle(key, resource);
2475
+
2476
+ // Failure is recorded on the resource and observed through `completed`.
2477
+ this.GetObject(path, request).catch(() => {});
2478
+ return true;
2479
+ } catch {
2480
+ return false;
2481
+ }
2482
+ }
2483
+
2484
+ /**
2485
+ * Give one resource the liveness callbacks its consumers never manage
2486
+ * themselves: activity renewal, payload renewal, lock counting, and the
2487
+ * reload hook that revives the handle after a purge.
2488
+ *
2489
+ * Ownership is captured by generation, so a late release can never renew or
2490
+ * unlock a rebound owner. The reload hook is bound outside the lifecycle
2491
+ * controller because that controller is detached exactly when canonical
2492
+ * ownership ends, which is precisely when a purged handle needs to come back.
2493
+ *
2494
+ * @param {string} key Canonical resolved key.
2495
+ * @param {object} resource Resource handle to bind.
2496
+ * @returns {object} The same resource handle.
2497
+ */
2123
2498
  #BindResourceLifecycle(key, resource) {
2124
2499
  const owner = this.motherLode;
2125
2500
  let ownership = this.#resourceOwnership.get(resource) || null;
@@ -2133,6 +2508,10 @@ class CjsResMan extends CjsEventEmitter {
2133
2508
  this.#resourceOwnership.set(resource, ownership);
2134
2509
  this.#invalidResourceOwnership.delete(resource);
2135
2510
  }
2511
+
2512
+ // Bound outside the lifecycle controller, which is detached when canonical
2513
+ // ownership ends - which is precisely when a handle needs to come back.
2514
+ resource?.SetReloadHook?.(() => this.#ReloadPurgedResource(key, resource));
2136
2515
  if (typeof resource?.SetLifecycleController !== "function") return resource;
2137
2516
  resource.SetLifecycleController(Object.freeze({
2138
2517
  isCurrent: () => this.#IsResourceOwnershipCurrent(ownership),
@@ -2189,10 +2568,10 @@ class CjsResMan extends CjsEventEmitter {
2189
2568
  */
2190
2569
  ReadFormatOnce(resource, descriptor, bytes, options = {}) {
2191
2570
  const read = this.#BeginReadOperation(resource.GetPath(), options);
2192
- const cachePolicy = NormalizeCachePolicy(read.options.cacheFormat, "cacheFormat");
2193
- const key = GetFormatOperationKey(read.context, read.options);
2571
+ const cachePolicy = normalizeCachePolicy(read.options.cacheFormat, "cacheFormat");
2572
+ const key = getFormatOperationKey(read.context, read.options);
2194
2573
  const cacheableOptions = key !== null && cachePolicy !== false;
2195
- const descriptorOperations = cacheableOptions ? GetFormatDescriptorOperations(this.formatOperations, read.context.source, descriptor, true) : null;
2574
+ const descriptorOperations = cacheableOptions ? getFormatDescriptorOperations(this.formatOperations, read.context.source, descriptor, true) : null;
2196
2575
  const bypassExisting = read.options.reload === true || !cacheableOptions;
2197
2576
  const existing = bypassExisting ? null : descriptorOperations.get(key);
2198
2577
  if (existing) {
@@ -2232,11 +2611,11 @@ class CjsResMan extends CjsEventEmitter {
2232
2611
  * @returns {Readonly<object>} Deeply frozen plain defaults snapshot.
2233
2612
  * @throws {TypeError} If defaults contain unsupported objects, accessors, symbols, or byte buffers.
2234
2613
  */
2235
- function SnapshotFormatDefaults(defaults, seen = new WeakMap()) {
2614
+ function snapshotFormatDefaults(defaults, seen = new WeakMap()) {
2236
2615
  if (!defaults || typeof defaults !== "object" || Array.isArray(defaults)) {
2237
2616
  throw new TypeError("CjsResMan format defaults must be a plain object.");
2238
2617
  }
2239
- return SnapshotFormatDefaultValue(defaults, seen, "defaults");
2618
+ return snapshotFormatDefaultValue(defaults, seen, "defaults");
2240
2619
  }
2241
2620
 
2242
2621
  /**
@@ -2248,7 +2627,7 @@ function SnapshotFormatDefaults(defaults, seen = new WeakMap()) {
2248
2627
  * @returns {*} Frozen snapshot value or stable primitive/function leaf.
2249
2628
  * @throws {TypeError} If the value cannot be made structurally immutable.
2250
2629
  */
2251
- function SnapshotFormatDefaultValue(value, seen, path) {
2630
+ function snapshotFormatDefaultValue(value, seen, path) {
2252
2631
  if (value === null || value === undefined) return value;
2253
2632
  const type = typeof value;
2254
2633
  if (["string", "number", "boolean", "bigint"].includes(type)) return value;
@@ -2262,10 +2641,10 @@ function SnapshotFormatDefaultValue(value, seen, path) {
2262
2641
  const snapshot = [];
2263
2642
  seen.set(value, snapshot);
2264
2643
  for (let index = 0; index < value.length; index += 1) {
2265
- if (!Object.prototype.hasOwnProperty.call(value, index)) {
2644
+ if (!hasOwn(value, index)) {
2266
2645
  throw new TypeError(`CjsResMan format ${path} must not contain sparse arrays.`);
2267
2646
  }
2268
- snapshot.push(SnapshotFormatDefaultValue(value[index], seen, `${path}[${index}]`));
2647
+ snapshot.push(snapshotFormatDefaultValue(value[index], seen, `${path}[${index}]`));
2269
2648
  }
2270
2649
  return Object.freeze(snapshot);
2271
2650
  }
@@ -2283,7 +2662,7 @@ function SnapshotFormatDefaultValue(value, seen, path) {
2283
2662
  if (!descriptor.enumerable || !("value" in descriptor)) {
2284
2663
  throw new TypeError(`CjsResMan format ${path}.${key} must be an enumerable data property.`);
2285
2664
  }
2286
- snapshot[key] = SnapshotFormatDefaultValue(descriptor.value, seen, `${path}.${key}`);
2665
+ snapshot[key] = snapshotFormatDefaultValue(descriptor.value, seen, `${path}.${key}`);
2287
2666
  }
2288
2667
  return Object.freeze(snapshot);
2289
2668
  }
@@ -2297,7 +2676,7 @@ function SnapshotFormatDefaultValue(value, seen, path) {
2297
2676
  * @returns {string} Type-stable internal revision key.
2298
2677
  * @throws {TypeError} If the token is neither a string nor finite number.
2299
2678
  */
2300
- function NormalizeSourceRevision(value) {
2679
+ function normalizeSourceRevision(value) {
2301
2680
  if (value === undefined) return "undefined";
2302
2681
  if (typeof value === "string") return `string:${value}`;
2303
2682
  if (typeof value === "number" && Number.isFinite(value)) {
@@ -2314,7 +2693,7 @@ function NormalizeSourceRevision(value) {
2314
2693
  * @returns {boolean|undefined} The validated policy.
2315
2694
  * @throws {TypeError} If the value is not boolean or omitted.
2316
2695
  */
2317
- function NormalizeCachePolicy(value, name) {
2696
+ function normalizeCachePolicy(value, name) {
2318
2697
  if (value !== undefined && typeof value !== "boolean") {
2319
2698
  throw new TypeError(`CjsResMan ${name} must be a boolean when supplied.`);
2320
2699
  }
@@ -2329,7 +2708,7 @@ function NormalizeCachePolicy(value, name) {
2329
2708
  * @param {boolean} create Whether a missing map should be allocated.
2330
2709
  * @returns {Map<string, CjsResourceReadOperationRecord>|null} Owner map or `null`.
2331
2710
  */
2332
- function GetOwnerOperations(ledger, owner, create) {
2711
+ function getOwnerOperations(ledger, owner, create) {
2333
2712
  let operations = ledger.get(owner);
2334
2713
  if (!operations && create) {
2335
2714
  operations = new Map();
@@ -2344,7 +2723,7 @@ function GetOwnerOperations(ledger, owner, create) {
2344
2723
  * @param {Readonly<CjsResourceReadContext>} context Normalized provenance.
2345
2724
  * @returns {string} Internal read-operation key.
2346
2725
  */
2347
- function GetReadOperationKey(context) {
2726
+ function getReadOperationKey(context) {
2348
2727
  return `${context.path}\u0000${context.revisionKey}`;
2349
2728
  }
2350
2729
 
@@ -2358,7 +2737,7 @@ function GetReadOperationKey(context) {
2358
2737
  * @param {boolean} create Whether missing maps should be allocated.
2359
2738
  * @returns {Map<string, CjsResourceReadOperationRecord>|null} Descriptor map or `null`.
2360
2739
  */
2361
- function GetFormatDescriptorOperations(ledger, source, descriptor, create) {
2740
+ function getFormatDescriptorOperations(ledger, source, descriptor, create) {
2362
2741
  let descriptors = ledger.get(source);
2363
2742
  if (!descriptors && create) {
2364
2743
  descriptors = new Map();
@@ -2383,10 +2762,10 @@ function GetFormatDescriptorOperations(ledger, source, descriptor, create) {
2383
2762
  * @param {object} options Format request options.
2384
2763
  * @returns {string|null} Internal format-operation key, or `null` to bypass caching.
2385
2764
  */
2386
- function GetFormatOperationKey(context, options) {
2765
+ function getFormatOperationKey(context, options) {
2387
2766
  const material = [options.emit, options.mediaType, options.classes, options.formatOptions];
2388
- if (!material.every(value => IsCanonicalFormatCacheValue(value))) return null;
2389
- return `${GetReadOperationKey(context)}\u0000${material.map(value => SerializeFormatCacheValue(value)).join("\u0001")}`;
2767
+ if (!material.every(value => isCanonicalFormatCacheValue(value))) return null;
2768
+ return `${getReadOperationKey(context)}\u0000${material.map(value => serializeFormatCacheValue(value)).join("\u0001")}`;
2390
2769
  }
2391
2770
 
2392
2771
  /**
@@ -2399,7 +2778,7 @@ function GetFormatOperationKey(context, options) {
2399
2778
  * @param {WeakSet<object|Function>} [seen=new WeakSet()] Cycle guard.
2400
2779
  * @returns {boolean} Whether deterministic cache serialization is supported.
2401
2780
  */
2402
- function IsCanonicalFormatCacheValue(value, seen = new WeakSet()) {
2781
+ function isCanonicalFormatCacheValue(value, seen = new WeakSet()) {
2403
2782
  if (value === null || value === undefined) return true;
2404
2783
  if (["string", "number", "boolean", "bigint"].includes(typeof value)) return true;
2405
2784
  if (typeof value === "function") return true;
@@ -2408,14 +2787,14 @@ function IsCanonicalFormatCacheValue(value, seen = new WeakSet()) {
2408
2787
  if (seen.has(value)) return true;
2409
2788
  seen.add(value);
2410
2789
  if (Array.isArray(value)) {
2411
- return value.every(entry => IsCanonicalFormatCacheValue(entry, seen));
2790
+ return value.every(entry => isCanonicalFormatCacheValue(entry, seen));
2412
2791
  }
2413
2792
  const prototype = Object.getPrototypeOf(value);
2414
2793
  if (prototype !== Object.prototype && prototype !== null) return false;
2415
2794
  if (Object.getOwnPropertySymbols(value).length > 0) return false;
2416
2795
  return Object.getOwnPropertyNames(value).every(key => {
2417
2796
  const descriptor = Object.getOwnPropertyDescriptor(value, key);
2418
- return descriptor.enumerable && "value" in descriptor && IsCanonicalFormatCacheValue(descriptor.value, seen);
2797
+ return descriptor.enumerable && "value" in descriptor && isCanonicalFormatCacheValue(descriptor.value, seen);
2419
2798
  });
2420
2799
  }
2421
2800
 
@@ -2429,7 +2808,7 @@ function IsCanonicalFormatCacheValue(value, seen = new WeakSet()) {
2429
2808
  * @param {WeakSet<object|Function>} [seen=new WeakSet()] Cycle guard.
2430
2809
  * @returns {string} Deterministic cache-local representation.
2431
2810
  */
2432
- function SerializeFormatCacheValue(value, seen = new WeakSet()) {
2811
+ function serializeFormatCacheValue(value, seen = new WeakSet()) {
2433
2812
  if (value === undefined) return "undefined";
2434
2813
  if (value === null) return "null";
2435
2814
  if (typeof value === "string") return `string:${JSON.stringify(value)}`;
@@ -2440,8 +2819,8 @@ function SerializeFormatCacheValue(value, seen = new WeakSet()) {
2440
2819
  }
2441
2820
  if (typeof value === "boolean") return `boolean:${value}`;
2442
2821
  if (typeof value === "bigint") return `bigint:${value}`;
2443
- if (typeof value === "function") return `function:${GetLocalValueIdentity(value)}`;
2444
- const identity = GetLocalValueIdentity(value);
2822
+ if (typeof value === "function") return `function:${getLocalValueIdentity(value)}`;
2823
+ const identity = getLocalValueIdentity(value);
2445
2824
  if (seen.has(value)) return `reference:${identity}`;
2446
2825
  seen.add(value);
2447
2826
  if (ArrayBuffer.isView(value)) {
@@ -2452,9 +2831,9 @@ function SerializeFormatCacheValue(value, seen = new WeakSet()) {
2452
2831
  return `buffer:${identity}:${[...new Uint8Array(value)].join(",")}`;
2453
2832
  }
2454
2833
  if (Array.isArray(value)) {
2455
- return `array:${identity}:[${value.map(entry => SerializeFormatCacheValue(entry, seen)).join(",")}]`;
2834
+ return `array:${identity}:[${value.map(entry => serializeFormatCacheValue(entry, seen)).join(",")}]`;
2456
2835
  }
2457
- return `object:${identity}:{${Object.keys(value).sort().map(key => `${JSON.stringify(key)}:${SerializeFormatCacheValue(value[key], seen)}`).join(",")}}`;
2836
+ return `object:${identity}:{${Object.keys(value).sort().map(key => `${JSON.stringify(key)}:${serializeFormatCacheValue(value[key], seen)}`).join(",")}}`;
2458
2837
  }
2459
2838
 
2460
2839
  /**
@@ -2463,7 +2842,7 @@ function SerializeFormatCacheValue(value, seen = new WeakSet()) {
2463
2842
  * @param {object|Function} value Candidate option identity owner.
2464
2843
  * @returns {number} Stable identity for the life of the value.
2465
2844
  */
2466
- function GetLocalValueIdentity(value) {
2845
+ function getLocalValueIdentity(value) {
2467
2846
  let identity = LOCAL_VALUE_IDENTITIES.get(value);
2468
2847
  if (!identity) {
2469
2848
  identity = nextLocalValueIdentity++;
@@ -2481,7 +2860,7 @@ function GetLocalValueIdentity(value) {
2481
2860
  * @param {string|null} revisionKey Exact revision or `null` for all revisions.
2482
2861
  * @returns {number} Number of detached records.
2483
2862
  */
2484
- function RemoveOperationRecords(operations, path, revisionKey) {
2863
+ function removeOperationRecords(operations, path, revisionKey) {
2485
2864
  if (!operations) return 0;
2486
2865
  let removed = 0;
2487
2866
  for (const [key, record] of operations) {
@@ -2500,7 +2879,7 @@ function RemoveOperationRecords(operations, path, revisionKey) {
2500
2879
  * @param {object} [options={}] Original resource request.
2501
2880
  * @returns {object} Shallow reconstruction request without cache/reload policy.
2502
2881
  */
2503
- function GetResourceRequestOptions(options = {}) {
2882
+ function getResourceRequestOptions(options = {}) {
2504
2883
  const request = {};
2505
2884
  for (const key of RESOURCE_REQUEST_OPTION_KEYS) {
2506
2885
  if (options[key] !== undefined) request[key] = options[key];
@@ -2518,11 +2897,11 @@ function GetResourceRequestOptions(options = {}) {
2518
2897
  * @param {object|Function|null} [effectiveSource=null] Source selected when the resource was created.
2519
2898
  * @returns {object} Detached loader options safe to retain with the resource.
2520
2899
  */
2521
- function GetResourceLoaderOptions(options = {}, effectiveSource = null) {
2522
- const loaderOptions = GetResourceRequestOptions(options);
2900
+ function getResourceLoaderOptions(options = {}, effectiveSource = null) {
2901
+ const loaderOptions = getResourceRequestOptions(options);
2523
2902
  if (effectiveSource) loaderOptions.source = effectiveSource;
2524
2903
  for (const key of ["sourceRevision", "ext"]) {
2525
- if (Object.prototype.hasOwnProperty.call(options, key)) {
2904
+ if (hasOwn(options, key)) {
2526
2905
  loaderOptions[key] = options[key];
2527
2906
  }
2528
2907
  }
@@ -2541,15 +2920,15 @@ function GetResourceLoaderOptions(options = {}, effectiveSource = null) {
2541
2920
  * @param {object} [overrides={}] Per-call operation controls.
2542
2921
  * @returns {object} Merged request with stable promised-output fields.
2543
2922
  */
2544
- function MergeResourceLoaderOptions(base, overrides = {}) {
2923
+ function mergeResourceLoaderOptions(base, overrides = {}) {
2545
2924
  const result = {
2546
2925
  ...base,
2547
2926
  ...overrides
2548
2927
  };
2549
- const pinsOutput = RESOURCE_OUTPUT_OPTION_KEYS.some(key => Object.prototype.hasOwnProperty.call(base, key) && base[key] !== undefined);
2928
+ const pinsOutput = RESOURCE_OUTPUT_OPTION_KEYS.some(key => hasOwn(base, key) && base[key] !== undefined);
2550
2929
  if (pinsOutput) {
2551
2930
  for (const key of RESOURCE_OUTPUT_OPTION_KEYS) {
2552
- if (Object.prototype.hasOwnProperty.call(base, key) && base[key] !== undefined) {
2931
+ if (hasOwn(base, key) && base[key] !== undefined) {
2553
2932
  result[key] = base[key];
2554
2933
  } else {
2555
2934
  delete result[key];
@@ -2557,7 +2936,7 @@ function MergeResourceLoaderOptions(base, overrides = {}) {
2557
2936
  }
2558
2937
  }
2559
2938
  for (const key of RESOURCE_PROVENANCE_OPTION_KEYS) {
2560
- if (Object.prototype.hasOwnProperty.call(base, key)) result[key] = base[key];
2939
+ if (hasOwn(base, key)) result[key] = base[key];
2561
2940
  }
2562
2941
  return result;
2563
2942
  }
@@ -2570,7 +2949,7 @@ function MergeResourceLoaderOptions(base, overrides = {}) {
2570
2949
  * @param {object} options Format, output, and media selection.
2571
2950
  * @returns {object[]} Matching descriptors in registration order.
2572
2951
  */
2573
- function FilterFormatDescriptors(descriptors, options) {
2952
+ function filterFormatDescriptors(descriptors, options) {
2574
2953
  let candidates = [...descriptors];
2575
2954
  if (options.format) {
2576
2955
  candidates = candidates.filter(({
@@ -2580,7 +2959,7 @@ function FilterFormatDescriptors(descriptors, options) {
2580
2959
  if (options.emit !== undefined) {
2581
2960
  candidates = candidates.filter(({
2582
2961
  Format
2583
- }) => FindDeclaredOutput(GetFormatOutputs(Format), options.emit) !== null);
2962
+ }) => findDeclaredOutput(getFormatOutputs(Format), options.emit) !== null);
2584
2963
  }
2585
2964
  if (options.mediaType) {
2586
2965
  candidates = candidates.filter(({
@@ -2596,7 +2975,7 @@ function FilterFormatDescriptors(descriptors, options) {
2596
2975
  * @param {Function} Format Registered format facade.
2597
2976
  * @returns {Array<*>} Declared output values in selection order.
2598
2977
  */
2599
- function GetFormatOutputs(Format) {
2978
+ function getFormatOutputs(Format) {
2600
2979
  return [...(Format.outputTypes || []), ...(Format.debugOutputTypes || [])];
2601
2980
  }
2602
2981
 
@@ -2609,11 +2988,11 @@ function GetFormatOutputs(Format) {
2609
2988
  * @param {*} requested Requested output selector.
2610
2989
  * @returns {string|null} Canonical declaration, or `null` when unsupported.
2611
2990
  */
2612
- function FindDeclaredOutput(outputs, requested) {
2613
- const normalized = NormalizeResourceVariant(requested);
2991
+ function findDeclaredOutput(outputs, requested) {
2992
+ const normalized = normalizeResourceVariant(requested);
2614
2993
  for (const output of outputs) {
2615
2994
  if (typeof output !== "string") continue;
2616
- if (NormalizeResourceVariant(output) === normalized) return output;
2995
+ if (normalizeResourceVariant(output) === normalized) return output;
2617
2996
  }
2618
2997
  return null;
2619
2998
  }
@@ -2627,7 +3006,7 @@ function FindDeclaredOutput(outputs, requested) {
2627
3006
  * @param {readonly object[]} descriptors Registered input-format descriptors.
2628
3007
  * @returns {Error} Contextual unsupported-output error.
2629
3008
  */
2630
- function CreateFormatOutputMissingError(ext, emit, descriptors) {
3009
+ function createFormatOutputMissingError(ext, emit, descriptors) {
2631
3010
  const error = new Error(`No format registered for .${ext} emits ${JSON.stringify(emit)}.`);
2632
3011
  error.code = "CJS_RESOURCE_FORMAT_OUTPUT_MISSING";
2633
3012
  error.ext = ext;
@@ -2646,7 +3025,7 @@ function CreateFormatOutputMissingError(ext, emit, descriptors) {
2646
3025
  * @param {*} emit Requested output tag.
2647
3026
  * @returns {Error} Contextual unsupported-output error.
2648
3027
  */
2649
- function CreateObjectLoaderOutputMissingError(ext, emit) {
3028
+ function createObjectLoaderOutputMissingError(ext, emit) {
2650
3029
  const error = new Error(`Direct loader for .${ext} exposes only its unforced default; it does not emit ${JSON.stringify(emit)}.`);
2651
3030
  error.code = "CJS_RESOURCE_FORMAT_OUTPUT_MISSING";
2652
3031
  error.ext = ext;
@@ -2665,7 +3044,7 @@ function CreateObjectLoaderOutputMissingError(ext, emit) {
2665
3044
  * @returns {object} Selected descriptor.
2666
3045
  * @throws {Error} If the candidate set is missing or remains ambiguous.
2667
3046
  */
2668
- function ResolveFormatDescriptorCandidates(descriptors, ext, options) {
3047
+ function resolveFormatDescriptorCandidates(descriptors, ext, options) {
2669
3048
  let candidates = [...descriptors];
2670
3049
  if (candidates.length > 1 && options.bytes !== undefined) {
2671
3050
  const supported = candidates.filter(descriptor => {
@@ -2700,7 +3079,7 @@ function ResolveFormatDescriptorCandidates(descriptors, ext, options) {
2700
3079
  }
2701
3080
  return candidates[0];
2702
3081
  }
2703
- function NormalizeRequirement(value) {
3082
+ function normalizeRequirement(value) {
2704
3083
  return value === null || value === undefined ? "" : String(value).trim().toLowerCase();
2705
3084
  }
2706
3085
 
@@ -2711,7 +3090,7 @@ function NormalizeRequirement(value) {
2711
3090
  * @returns {string} Trimmed lowercase tag, or an empty string.
2712
3091
  * @throws {TypeError} If a non-empty tag is not a string or contains the internal key delimiter.
2713
3092
  */
2714
- function NormalizeResourceVariant(value) {
3093
+ function normalizeResourceVariant(value) {
2715
3094
  if (value === null || value === undefined || value === "") return "";
2716
3095
  if (typeof value !== "string") {
2717
3096
  throw new TypeError("CjsResMan resource variant must be a string.");
@@ -2722,7 +3101,7 @@ function NormalizeResourceVariant(value) {
2722
3101
  }
2723
3102
  return normalized;
2724
3103
  }
2725
- function CreatePrepareContext(resMan, resource, bytes, options, stage) {
3104
+ function createPrepareContext(resMan, resource, bytes, options, stage) {
2726
3105
  return Object.freeze({
2727
3106
  ...options,
2728
3107
  stage,
@@ -2742,20 +3121,20 @@ function CreatePrepareContext(resMan, resource, bytes, options, stage) {
2742
3121
  * @param {CjsResource} resource Resource with an attached CPU payload.
2743
3122
  * @returns {*} Resident public object outcome.
2744
3123
  */
2745
- function GetPublishedResourceObject(resource) {
3124
+ function getPublishedResourceObject(resource) {
2746
3125
  return resource.constructor !== _CjsResource ? resource : resource.GetPayload();
2747
3126
  }
2748
- function AssertPositiveInteger(value, name) {
3127
+ function assertPositiveInteger(value, name) {
2749
3128
  if (!Number.isInteger(value) || value < 1) {
2750
3129
  throw new TypeError(`CjsResMan ${name} must be a positive integer.`);
2751
3130
  }
2752
3131
  }
2753
- function AssertNonNegativeInteger(value, name) {
3132
+ function assertNonNegativeInteger(value, name) {
2754
3133
  if (!Number.isInteger(value) || value < 0) {
2755
3134
  throw new TypeError(`CjsResMan ${name} must be a non-negative integer.`);
2756
3135
  }
2757
3136
  }
2758
- function AssertNonNegativeNumber(value, name) {
3137
+ function assertNonNegativeNumber(value, name) {
2759
3138
  if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
2760
3139
  throw new TypeError(`CjsResMan ${name} must be a non-negative finite number.`);
2761
3140
  }
@@ -2768,7 +3147,7 @@ function AssertNonNegativeNumber(value, name) {
2768
3147
  * @returns {Readonly<CjsResManAutoPurgePolicy>|null} Frozen normalized policy, or `null` when disabled.
2769
3148
  * @throws {TypeError} If fields, limits, cleanup controls, or the cadence clock are invalid.
2770
3149
  */
2771
- function NormalizeAutoPurgePolicy(policy) {
3150
+ function normalizeAutoPurgePolicy(policy) {
2772
3151
  if (policy === null || policy === undefined || policy === false) return null;
2773
3152
  if (!policy || typeof policy !== "object" || Array.isArray(policy)) {
2774
3153
  throw new TypeError("CjsResMan autoPurgePolicy must be an object, false, or null.");
@@ -2779,10 +3158,10 @@ function NormalizeAutoPurgePolicy(policy) {
2779
3158
  throw new TypeError(`CjsResMan autoPurgePolicy does not support: ${unsupported.join(", ")}.`);
2780
3159
  }
2781
3160
  const intervalMilliseconds = policy.intervalMilliseconds ?? 1000;
2782
- AssertNonNegativeNumber(intervalMilliseconds, "autoPurgePolicy.intervalMilliseconds");
3161
+ assertNonNegativeNumber(intervalMilliseconds, "autoPurgePolicy.intervalMilliseconds");
2783
3162
  for (const name of ["maxIdleMilliseconds", "payloadMaxIdleMilliseconds"]) {
2784
3163
  if (policy[name] !== undefined) {
2785
- AssertNonNegativeNumber(policy[name], `autoPurgePolicy.${name}`);
3164
+ assertNonNegativeNumber(policy[name], `autoPurgePolicy.${name}`);
2786
3165
  }
2787
3166
  }
2788
3167
  if (policy.maxIdleMilliseconds === undefined && policy.payloadMaxIdleMilliseconds === undefined) {
@@ -2808,7 +3187,7 @@ function NormalizeAutoPurgePolicy(policy) {
2808
3187
  ...(policy.cleanup === undefined ? {} : {
2809
3188
  cleanup: policy.cleanup
2810
3189
  }),
2811
- now: policy.now || DefaultAutoPurgeNow
3190
+ now: policy.now || defaultAutoPurgeNow
2812
3191
  });
2813
3192
  }
2814
3193
 
@@ -2819,7 +3198,7 @@ function NormalizeAutoPurgePolicy(policy) {
2819
3198
  * @returns {CjsResManAutoPurgePumpOptions} Validated options.
2820
3199
  * @throws {TypeError} If options or an explicit timestamp are invalid.
2821
3200
  */
2822
- function NormalizeAutoPurgePumpOptions(options) {
3201
+ function normalizeAutoPurgePumpOptions(options) {
2823
3202
  if (!options || typeof options !== "object" || Array.isArray(options)) {
2824
3203
  throw new TypeError("CjsResMan automatic purge options must be an object.");
2825
3204
  }
@@ -2828,7 +3207,7 @@ function NormalizeAutoPurgePumpOptions(options) {
2828
3207
  throw new TypeError(`CjsResMan automatic purge options do not support: ${unsupported.join(", ")}.`);
2829
3208
  }
2830
3209
  if (options.time !== undefined) {
2831
- AssertNonNegativeNumber(options.time, "automatic purge time");
3210
+ assertNonNegativeNumber(options.time, "automatic purge time");
2832
3211
  }
2833
3212
  return options;
2834
3213
  }
@@ -2840,7 +3219,7 @@ function NormalizeAutoPurgePumpOptions(options) {
2840
3219
  * @param {number} activeOperations Number of queued and direct mutations.
2841
3220
  * @returns {Error} Contextual active-operation error.
2842
3221
  */
2843
- function ActiveResourceOperationsError(activeOperations) {
3222
+ function activeResourceOperationsError(activeOperations) {
2844
3223
  const error = new Error(`CjsResMan cannot replace MotherLode while ${activeOperations} resource operation(s) are active.`);
2845
3224
  error.code = "CJS_RESMAN_ACTIVE_RESOURCE_OPERATIONS";
2846
3225
  error.activeOperations = activeOperations;
@@ -2855,8 +3234,8 @@ function ActiveResourceOperationsError(activeOperations) {
2855
3234
  * @param {string} phase Operation phase.
2856
3235
  * @returns {Error} Contextual ownership error.
2857
3236
  */
2858
- function ResourceNotOwnedError(resource, phase) {
2859
- const path = GetResourceDiagnosticPath(resource);
3237
+ function resourceNotOwnedError(resource, phase) {
3238
+ const path = getResourceDiagnosticPath(resource);
2860
3239
  const error = new Error(`CjsResMan does not own a canonical resource at ${path}.`);
2861
3240
  error.code = "CJS_RESMAN_RESOURCE_NOT_OWNED";
2862
3241
  error.resource = resource;
@@ -2873,8 +3252,8 @@ function ResourceNotOwnedError(resource, phase) {
2873
3252
  * @param {string} phase Operation phase that detected staleness.
2874
3253
  * @returns {Error} Contextual stale-operation error.
2875
3254
  */
2876
- function StaleResourceOperationError(ownership, phase) {
2877
- const path = GetResourceDiagnosticPath(ownership?.resource);
3255
+ function staleResourceOperationError(ownership, phase) {
3256
+ const path = getResourceDiagnosticPath(ownership?.resource);
2878
3257
  const error = new Error(`CjsResMan resource operation became stale during ${phase}: ${path}.`);
2879
3258
  error.code = "CJS_RESMAN_STALE_RESOURCE_OPERATION";
2880
3259
  error.resource = ownership?.resource || null;
@@ -2893,7 +3272,7 @@ function StaleResourceOperationError(ownership, phase) {
2893
3272
  * @param {object|Function} resource Aliased canonical resource.
2894
3273
  * @returns {Error} Stable candidate-alias error.
2895
3274
  */
2896
- function ReloadCandidateAliasError(path, resource) {
3275
+ function reloadCandidateAliasError(path, resource) {
2897
3276
  const error = new Error(`CjsResMan reload candidate aliases the canonical resource: ${path}.`);
2898
3277
  error.code = "CJS_RESMAN_RELOAD_CANDIDATE_ALIAS";
2899
3278
  error.path = path;
@@ -2908,8 +3287,8 @@ function ReloadCandidateAliasError(path, resource) {
2908
3287
  * @param {object|Function} resource Candidate resource.
2909
3288
  * @returns {Error} Stable unavailable-candidate error.
2910
3289
  */
2911
- function ReloadCandidateUnavailableError(resource) {
2912
- const path = GetResourceDiagnosticPath(resource);
3290
+ function reloadCandidateUnavailableError(resource) {
3291
+ const path = getResourceDiagnosticPath(resource);
2913
3292
  const error = new Error(`CjsResMan reload candidate is no longer available: ${path}.`);
2914
3293
  error.code = "CJS_RESMAN_RELOAD_CANDIDATE_UNAVAILABLE";
2915
3294
  error.path = path;
@@ -2925,8 +3304,8 @@ function ReloadCandidateUnavailableError(resource) {
2925
3304
  * @param {string} phase Operation phase that detected staleness.
2926
3305
  * @returns {Error} Contextual stale-candidate error.
2927
3306
  */
2928
- function StaleReloadCandidateError(candidate, phase) {
2929
- const path = GetResourceDiagnosticPath(candidate?.resource);
3307
+ function staleReloadCandidateError(candidate, phase) {
3308
+ const path = getResourceDiagnosticPath(candidate?.resource);
2930
3309
  const error = new Error(`CjsResMan reload candidate became stale during ${phase}: ${path}.`);
2931
3310
  error.code = "CJS_RESMAN_STALE_RELOAD_CANDIDATE";
2932
3311
  error.resource = candidate?.resource || null;
@@ -2945,7 +3324,7 @@ function StaleReloadCandidateError(candidate, phase) {
2945
3324
  * @param {*} resource Candidate resource.
2946
3325
  * @returns {string} Best-effort resource path label.
2947
3326
  */
2948
- function GetResourceDiagnosticPath(resource) {
3327
+ function getResourceDiagnosticPath(resource) {
2949
3328
  try {
2950
3329
  return String(resource?.GetPath?.() || resource?.path || "<unknown>");
2951
3330
  } catch {
@@ -2958,23 +3337,133 @@ function GetResourceDiagnosticPath(resource) {
2958
3337
  *
2959
3338
  * @returns {void}
2960
3339
  */
2961
- function Noop() {}
3340
+ function noop() {}
3341
+
3342
+ /**
3343
+ * Validate a resource execution strategy.
3344
+ *
3345
+ * @param {*} loader Candidate loader.
3346
+ * @param {string} name Configuration field name.
3347
+ * @returns {void}
3348
+ */
3349
+ function assertResourceLoader(loader, name) {
3350
+ if (!isResourceLoader(loader)) {
3351
+ throw new TypeError(`CjsResMan ${name} must provide Read and ReadFormat.`);
3352
+ }
3353
+ }
3354
+
3355
+ /**
3356
+ * Test the structural resource loader contract.
3357
+ *
3358
+ * @param {*} loader Candidate loader.
3359
+ * @returns {boolean}
3360
+ */
3361
+ function isResourceLoader(loader) {
3362
+ return Boolean(loader && typeof loader.Read === "function" && typeof loader.ReadFormat === "function");
3363
+ }
3364
+
3365
+ /**
3366
+ * Merge frozen registration defaults with one request's format overrides.
3367
+ *
3368
+ * @param {object} descriptor Registered format descriptor.
3369
+ * @param {object} options Resource read options.
3370
+ * @returns {object} Effective format reader options.
3371
+ */
3372
+ function createFormatReadOptions(descriptor, options) {
3373
+ const {
3374
+ Format,
3375
+ defaults
3376
+ } = descriptor;
3377
+ const formatOptions = {
3378
+ ...defaults,
3379
+ ...(options.formatOptions || {})
3380
+ };
3381
+ if (options.emit !== undefined) {
3382
+ formatOptions.emit = findDeclaredOutput(getFormatOutputs(Format), options.emit) ?? options.emit;
3383
+ }
3384
+ if (options.classes !== undefined) formatOptions.classes = options.classes;
3385
+ return formatOptions;
3386
+ }
3387
+
3388
+ /**
3389
+ * Reports whether a source requires CjsResMan to build a URL before reading.
3390
+ *
3391
+ * @param {*} source Selected source/provider.
3392
+ * @returns {boolean}
3393
+ */
3394
+ function sourceRequiresUrl(source) {
3395
+ return source?.requiresUrl === true || source?.constructor?.requiresUrl === true;
3396
+ }
3397
+
3398
+ /**
3399
+ * Tests whether an object owns one property.
3400
+ *
3401
+ * @param {*} object Candidate object.
3402
+ * @param {string|number|symbol} property Property key.
3403
+ * @returns {boolean}
3404
+ */
3405
+ function hasOwn(object, property) {
3406
+ return Object.prototype.hasOwnProperty.call(object, property);
3407
+ }
3408
+
3409
+ /**
3410
+ * Normalizes one resource-path scheme key.
3411
+ *
3412
+ * @param {*} value Candidate scheme.
3413
+ * @returns {string}
3414
+ */
3415
+ function normalizePathPrefix(value) {
3416
+ const prefix = String(value ?? "").trim().replace(/:\/?$/u, "").toLowerCase();
3417
+ if (!/^[a-z][a-z0-9+.-]*$/u.test(prefix)) {
3418
+ throw new TypeError("CjsResMan path prefixes must be URI scheme names.");
3419
+ }
3420
+ return prefix;
3421
+ }
3422
+
3423
+ /**
3424
+ * Normalizes one registered URL base without altering case-sensitive path
3425
+ * content.
3426
+ *
3427
+ * @param {*} value Candidate URL base.
3428
+ * @returns {string}
3429
+ */
3430
+ function normalizeUrlBase(value) {
3431
+ const url = normalizePath(value);
3432
+ if (!url || url.includes("\0")) {
3433
+ throw new TypeError("CjsResMan path URL bases must be non-empty strings.");
3434
+ }
3435
+ return url.endsWith("/") ? url : `${url}/`;
3436
+ }
3437
+
3438
+ /**
3439
+ * Validates a URL returned by an injected path resolver.
3440
+ *
3441
+ * @param {*} value Resolver output.
3442
+ * @returns {string}
3443
+ */
3444
+ function normalizeResolvedUrl(value) {
3445
+ const url = normalizePath(value);
3446
+ if (!url || url.includes("\0")) {
3447
+ throw new TypeError("CjsResMan pathResolver must return a non-empty URL string.");
3448
+ }
3449
+ return url;
3450
+ }
2962
3451
 
2963
3452
  /**
2964
3453
  * Return the wall-clock timestamp used by default automatic purge cadence.
2965
3454
  *
2966
3455
  * @returns {number} Milliseconds since the Unix epoch.
2967
3456
  */
2968
- function DefaultAutoPurgeNow() {
3457
+ function defaultAutoPurgeNow() {
2969
3458
  return Date.now();
2970
3459
  }
2971
- function DefaultQueueScheduler(callback) {
3460
+ function defaultQueueScheduler(callback) {
2972
3461
  return setTimeout(callback, 0);
2973
3462
  }
2974
- function DefaultQueueYield() {
3463
+ function defaultQueueYield() {
2975
3464
  return new Promise(resolve => setTimeout(resolve, 0));
2976
3465
  }
2977
- function NormalizeRegistrationEntries(value, keyed = false) {
3466
+ function normalizeRegistrationEntries(value, keyed = false) {
2978
3467
  if (value === null || value === undefined) return [];
2979
3468
  if (Array.isArray(value)) return value;
2980
3469
  if (typeof value === "function") return [value];