Skip to content

Commit

Permalink
chore: optimize lazy decorator
Browse files Browse the repository at this point in the history
  • Loading branch information
Jack-Works committed Oct 8, 2023
1 parent 31f1dea commit 3ce78d7
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 17 deletions.
5 changes: 5 additions & 0 deletions .changeset/seven-clouds-behave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@masknet/kit': patch
---

optimize lazy decorator
45 changes: 28 additions & 17 deletions src/ecmascript/lazyDecorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,41 @@
* ;@lazy accessor value = lazy.of(() => getData())
* }
*/
export function lazy<T, V>(
target: ClassAccessorDecoratorTarget<T, V>,
_context: ClassAccessorDecoratorContext<T, V>,
): ClassAccessorDecoratorResult<T, V> {
const { get, set } = target
let init = false
export function lazy<C, T>(
{ get, set }: ClassAccessorDecoratorTarget<C, T>,
{ name, static: s }: ClassAccessorDecoratorContext<C, T>,
): ClassAccessorDecoratorResult<C, T> {
let init: ((C: C) => T) | undefined = function (C: C) {
const f = get.call(C) as any as () => T
if (!(initMap ||= new WeakSet()).has(f))
throw new Error(
`Wrong usage of lazy decorator. Please write:\n @lazy${s ? ' static' : ''} accessor ${
typeof name === 'string' ? name : '[symbol]'
} = lazy.mark(() => ...)`,
)
const value = f()
init = undefined
set.call(C, value)
return value
}
return {
get() {
const val = get.call(this)
if (!init) {
if (typeof val !== 'function') throw new TypeError('Please use lazy.of(() => ...) to wrap the value.')
set.call(this, val())
init = true
}
return val
get(this: C) {
init?.(this)
return get.call(this)
},
set(val) {
init ||= true
set(this: C, val: T) {
init?.(this)
set.call(this, val)
},
}
}
let initMap: WeakSet<object>
/**
* DO NOT use this function without the lazy decorator! It actually returning the init function instead of the value
* @param init The init function
*/
lazy.of = <T extends any>(init: () => T): T => init as any
lazy.of = function <T>(init: (this: undefined) => T): T {
const f = Reflect.apply(Function.bind, init, [undefined])
;(initMap ||= new WeakSet()).add(f)
return f
}

0 comments on commit 3ce78d7

Please sign in to comment.