Skip to content

Commit 3ce78d7

Browse files
committed
chore: optimize lazy decorator
1 parent 31f1dea commit 3ce78d7

File tree

2 files changed

+33
-17
lines changed

2 files changed

+33
-17
lines changed

.changeset/seven-clouds-behave.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@masknet/kit': patch
3+
---
4+
5+
optimize lazy decorator

src/ecmascript/lazyDecorator.ts

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,41 @@
55
* ;@lazy accessor value = lazy.of(() => getData())
66
* }
77
*/
8-
export function lazy<T, V>(
9-
target: ClassAccessorDecoratorTarget<T, V>,
10-
_context: ClassAccessorDecoratorContext<T, V>,
11-
): ClassAccessorDecoratorResult<T, V> {
12-
const { get, set } = target
13-
let init = false
8+
export function lazy<C, T>(
9+
{ get, set }: ClassAccessorDecoratorTarget<C, T>,
10+
{ name, static: s }: ClassAccessorDecoratorContext<C, T>,
11+
): ClassAccessorDecoratorResult<C, T> {
12+
let init: ((C: C) => T) | undefined = function (C: C) {
13+
const f = get.call(C) as any as () => T
14+
if (!(initMap ||= new WeakSet()).has(f))
15+
throw new Error(
16+
`Wrong usage of lazy decorator. Please write:\n @lazy${s ? ' static' : ''} accessor ${
17+
typeof name === 'string' ? name : '[symbol]'
18+
} = lazy.mark(() => ...)`,
19+
)
20+
const value = f()
21+
init = undefined
22+
set.call(C, value)
23+
return value
24+
}
1425
return {
15-
get() {
16-
const val = get.call(this)
17-
if (!init) {
18-
if (typeof val !== 'function') throw new TypeError('Please use lazy.of(() => ...) to wrap the value.')
19-
set.call(this, val())
20-
init = true
21-
}
22-
return val
26+
get(this: C) {
27+
init?.(this)
28+
return get.call(this)
2329
},
24-
set(val) {
25-
init ||= true
30+
set(this: C, val: T) {
31+
init?.(this)
2632
set.call(this, val)
2733
},
2834
}
2935
}
36+
let initMap: WeakSet<object>
3037
/**
3138
* DO NOT use this function without the lazy decorator! It actually returning the init function instead of the value
3239
* @param init The init function
3340
*/
34-
lazy.of = <T extends any>(init: () => T): T => init as any
41+
lazy.of = function <T>(init: (this: undefined) => T): T {
42+
const f = Reflect.apply(Function.bind, init, [undefined])
43+
;(initMap ||= new WeakSet()).add(f)
44+
return f
45+
}

0 commit comments

Comments
 (0)