diff --git a/lib/utils/src/object.ts b/lib/utils/src/object.ts index bff78bd..7366f30 100644 --- a/lib/utils/src/object.ts +++ b/lib/utils/src/object.ts @@ -1,3 +1,4 @@ +import { asap } from '@revenge-mod/utils/callback' import { getCurrentStack } from './error' import type { AnyObject } from './types' @@ -104,17 +105,32 @@ export function defineLazyProperties( return Object.defineProperties(target, descs) } +// Fake symbol to represent uninitialized values in lazy properties. +const UninitializedSymbol = {} + function lazyPropDesc( key: K, loader: () => T[K], ): PropertyDescriptor { if (__BUILD_FLAG_DEBUG_LAZY_VALUES__) { - const value = loader() - if (value == null) DEBUG_warnNullishLazyValue(key) + let val: unknown | typeof UninitializedSymbol = UninitializedSymbol + const getOrLoadVal = () => { + try { + if (val === UninitializedSymbol) val = loader() + return val + } catch (error) { + DEBUG_warnFaultyLazyLoader(key, error) + val = null + } + } + + asap(() => { + if (getOrLoadVal() == null) DEBUG_warnNullishLazyValue(key) + }) return { configurable: true, - value, + get: getOrLoadVal, } } @@ -133,3 +149,10 @@ function DEBUG_warnNullishLazyValue(key: PropertyKey) { 2, ) } + +function DEBUG_warnFaultyLazyLoader(key: PropertyKey, error: unknown) { + nativeLoggingHook( + `\u001b[31mLazy property ${String(key)} threw an error during loading:\n${getCurrentStack()}\u001b[0m\nError: ${error}`, + 2, + ) +}