11import { getOwner , onCleanup } from "solid-js"
22import type { Loader } from "three"
3- import type { LoaderUrl } from "../types.ts"
4- import { load , type LoadOutput } from "../utils.ts"
3+ import type { LoaderData , LoaderUrl , PromiseMaybe } from "../types.ts"
4+ import { isRecord } from "../utils.ts"
55import { TreeRegistry } from "./tree-registry.ts"
66
77/**********************************************************************************/
@@ -20,10 +20,10 @@ export interface LoaderRegistry {
2020 * @param url The URL or path to the resource
2121 * @param data The resource promise or resolved data
2222 */
23- set < TData extends object , TUrl extends string | string [ ] > (
24- loader : Loader < TData , TUrl > ,
25- url : TUrl ,
26- data : Promise < TData > ,
23+ set < TLoader extends Loader < object , any > > (
24+ loader : TLoader ,
25+ url : LoaderUrl < TLoader > ,
26+ data : PromiseMaybe < LoaderData < TLoader > > ,
2727 ) : void
2828
2929 /**
@@ -32,54 +32,34 @@ export interface LoaderRegistry {
3232 * @param url The URL or path to the resource
3333 * @returns The resource promise, resolved data, or undefined if not found
3434 */
35- get < TData extends object , TUrl extends string | string [ ] > (
36- loader : Loader < TData , TUrl > ,
37- url : TUrl ,
35+ get < TLoader extends Loader < object , any > > (
36+ loader : TLoader ,
37+ url : LoaderUrl < TLoader > ,
3838 warn ?: boolean ,
39- ) : Promise < TData > | TData | undefined
39+ ) : PromiseMaybe < LoaderData < TLoader > > | undefined
4040}
4141
4242/**********************************************************************************/
4343/* */
44- /* Utils */
44+ /* Loader Registry */
4545/* */
4646/**********************************************************************************/
4747
48- /**
49- * Gets a resource from cache or loads and caches it.
50- * @param registry The cache registry to use
51- * @param loader The Three.js loader instance
52- * @param url The URL(s) to load
53- * @returns Promise resolving to the loaded resource
54- * @internal
55- */
56- export async function getOrInsertLoaderRegistry <
57- TLoader extends Loader < any , any > ,
58- TInput extends LoaderUrl < TLoader > | Record < string , LoaderUrl < TLoader > > ,
59- > ( registry : LoaderRegistry , loader : TLoader , url : TInput ) : Promise < LoadOutput < TLoader , TInput > > {
60- const cachedPromise = registry . get ( loader , url , false )
61-
62- if ( cachedPromise ) {
63- return cachedPromise
64- }
65-
66- const promise = load ( loader , url )
67- registry . set ( loader , url , promise )
68-
69- return promise
48+ interface LoaderTreeRegistryMap extends Map < Loader < any , any > , any > {
49+ get < TLoader extends Loader < object , any > > ( loader : TLoader ) : LoaderTreeRegistry < TLoader > | undefined
50+ set < TLoader extends Loader < object , any > > ( loader : TLoader , data : LoaderTreeRegistry < TLoader > ) : this
7051}
7152
72- /**********************************************************************************/
73- /* */
74- /* Loader Registry */
75- /* */
76- /**********************************************************************************/
53+ interface LoaderTreeRegistry < TLoader extends Loader < object , any > > extends TreeRegistry < object > {
54+ get ( paths : LoaderUrl < TLoader > , warn ?: boolean ) : CacheNode < TLoader >
55+ set ( paths : LoaderUrl < TLoader > , data : CacheNode < TLoader > ) : void
56+ }
7757
7858export class LoaderCache implements LoaderRegistry {
7959 /** Map of loader instances to their respective tree registries */
80- #registryMap = new Map < Loader < any , any > , TreeRegistry < CacheNode < object > > > ( )
60+ #treeRegistryMap: LoaderTreeRegistryMap = new Map ( ) as unknown as LoaderTreeRegistryMap
8161 /** Weak map for reverse lookup from data to cache nodes */
82- #dataMap = new WeakMap < object , CacheNode < object > > ( )
62+ #dataMap = new WeakMap < object , CacheNode < Loader < any , any > > > ( )
8363
8464 /** Set of resources that do not have active references and can be safely cleaned up. */
8565 freeList = new Set < object > ( )
@@ -90,12 +70,15 @@ export class LoaderCache implements LoaderRegistry {
9070 * @returns The tree registry for this loader
9171 * @private
9272 */
93- #registry< T extends object > ( loader : Loader < T , any > ) {
94- let registry = this . #registryMap . get ( loader )
73+ #registry< TLoader extends Loader < object , any > > ( loader : TLoader ) {
74+ let registry = this . #treeRegistryMap . get ( loader )
9575 if ( ! registry ) {
96- this . #registryMap. set ( loader , ( registry = new TreeRegistry ( ) ) )
76+ this . #treeRegistryMap. set (
77+ loader ,
78+ ( registry = new TreeRegistry ( ) as LoaderTreeRegistry < TLoader > ) ,
79+ )
9780 }
98- return registry as TreeRegistry < CacheNode < T > >
81+ return registry
9982 }
10083
10184 /**
@@ -104,7 +87,7 @@ export class LoaderCache implements LoaderRegistry {
10487 * @param options.force Force deletion even if not in free list
10588 * @private
10689 */
107- #delete( node : CacheNode < any > , { force } : { force ?: boolean } = { } ) {
90+ #delete( node : CacheNode < Loader < any , any > > , { force } : { force ?: boolean } = { } ) {
10891 if ( ! force && ! this . freeList . has ( node . data ) ) {
10992 console . error (
11093 `Attempting to delete a non-freed resource. Use { force: true } if you are sure you want to dispose` ,
@@ -143,18 +126,18 @@ export class LoaderCache implements LoaderRegistry {
143126 /**
144127 * Removes a resource from a specific loader's cache at the given path.
145128 * @param loader The Three.js loader instance
146- * @param path The URL or path to the resource
129+ * @param url The URL or path to the resource
147130 * @param options.force Force deletion even if resource has active references
148131 */
149- delete < TData extends object , TUrl extends string | string [ ] > (
150- loader : Loader < TData , TUrl > ,
151- path : TUrl ,
132+ delete < TLoader extends Loader < object , any > > (
133+ loader : TLoader ,
134+ url : LoaderUrl < TLoader > ,
152135 options ?: { force ?: boolean } ,
153136 ) {
154- const node = this . #registry( loader ) . get ( path )
137+ const node = this . #registry( loader ) ? .get ( url )
155138
156139 if ( ! node ) {
157- console . error ( `Error while deleting path ${ path } . Could not find CacheNode.` )
140+ console . error ( `Error while deleting path ${ url } . Could not find CacheNode.` )
158141 return
159142 }
160143
@@ -165,19 +148,18 @@ export class LoaderCache implements LoaderRegistry {
165148 * Retrieves a resource from the cache and tracks its usage.
166149 * Automatically integrates with Solid.js cleanup for reference counting.
167150 * @param loader The Three.js loader instance
168- * @param path The URL or path to the resource
151+ * @param url The URL or path to the resource
169152 * @returns The resource promise, resolved data, or undefined if not found
170153 */
171- get < TData extends object , TUrl extends string | string [ ] > (
172- loader : Loader < TData , TUrl > ,
173- path : TUrl ,
174- warn = true ,
175- ) {
176- const node = this . #registry( loader ) . get ( path , warn )
154+ get < TLoader extends Loader < object , any > > (
155+ loader : TLoader ,
156+ url : LoaderUrl < TLoader > ,
157+ warn ?: boolean ,
158+ ) : PromiseMaybe < LoaderData < TLoader > > | undefined {
159+ const node = this . #registry( loader ) ? .get ( url , warn )
177160
178161 if ( ! node ) return undefined
179162
180- node . track ( )
181163 return node . data
182164 }
183165
@@ -189,14 +171,14 @@ export class LoaderCache implements LoaderRegistry {
189171 * @param options.force Force update even if resource already exists
190172 * @returns The stored promise
191173 */
192- set < TData extends object , TUrl extends string | string [ ] > (
193- loader : Loader < TData , TUrl > ,
194- path : TUrl ,
195- data : Promise < TData > ,
174+ set < TLoader extends Loader < object , any > > (
175+ loader : TLoader ,
176+ path : LoaderUrl < TLoader > ,
177+ data : PromiseMaybe < LoaderData < TLoader > > ,
196178 options ?: { force ?: boolean } ,
197179 ) {
198180 const registry = this . #registry( loader )
199- let node = registry . get ( path , false )
181+ let node = registry ? .get ( path , false )
200182
201183 if ( node ) {
202184 node . update ( data , options )
@@ -215,11 +197,11 @@ export class LoaderCache implements LoaderRegistry {
215197 * @template T The type of Three.js resource (must be an object)
216198 * @internal
217199 */
218- class CacheNode < T extends object > {
200+ class CacheNode < TLoader extends Loader < any , any > > {
219201 /** Reference count for this resource */
220202 count = 0
221203 /** The cached resource (promise or resolved value) */
222- data : Promise < T > | T
204+ data : PromiseMaybe < LoaderData < TLoader > >
223205
224206 /**
225207 * Creates a new cache node.
@@ -230,9 +212,9 @@ class CacheNode<T extends object> {
230212 */
231213 constructor (
232214 public free : Set < object > ,
233- public registry : TreeRegistry < CacheNode < T > > ,
234- public path : string | string [ ] ,
235- promise : Promise < T > ,
215+ public registry : LoaderTreeRegistry < TLoader > ,
216+ public path : LoaderUrl < TLoader > ,
217+ promise : PromiseMaybe < LoaderData < TLoader > > ,
236218 ) {
237219 this . data = promise
238220 this . #set( promise )
@@ -243,9 +225,9 @@ class CacheNode<T extends object> {
243225 * @param promise The resource promise
244226 * @private
245227 */
246- #set( promise : Promise < T > ) {
228+ #set( promise : PromiseMaybe < LoaderData < TLoader > > ) {
247229 this . data = promise
248- promise . then ( value => {
230+ Promise . resolve ( promise ) . then ( value => {
249231 // Update data to resolved promise, if it hasn't been updated before
250232 if ( this . data === promise ) {
251233 this . data = value
@@ -258,8 +240,8 @@ class CacheNode<T extends object> {
258240 * @private
259241 */
260242 #dispose( ) {
261- if ( "dispose" in this . data && typeof this . data . dispose === "function" ) {
262- this . data . dispose ?. ( )
243+ if ( isRecord ( this . data ) && "dispose" in this . data && typeof this . data . dispose === "function" ) {
244+ this . data . dispose ( )
263245 }
264246 }
265247
@@ -302,7 +284,7 @@ class CacheNode<T extends object> {
302284 * @param data The new resource promise
303285 * @param options.force Force update and dispose current resource (default: true)
304286 */
305- update ( data : Promise < T > , { force = true } : { force ?: boolean } = { } ) {
287+ update ( data : PromiseMaybe < LoaderData < TLoader > > , { force = true } : { force ?: boolean } = { } ) {
306288 if ( this . data !== data && ! force ) {
307289 console . error (
308290 "Attempted to update already set resource. To overwrite and dispose of current resource, use { force: true } instead." ,
0 commit comments