idlize

Форк
0
115 строк · 4.1 Кб
1
/*
2
 * Copyright (c) 2022-2024 Huawei Device Co., Ltd.
3
 * Licensed under the Apache License, Version 2.0 (the "License");
4
 * you may not use this file except in compliance with the License.
5
 * You may obtain a copy of the License at
6
 *
7
 * http://www.apache.org/licenses/LICENSE-2.0
8
 *
9
 * Unless required by applicable law or agreed to in writing, software
10
 * distributed under the License is distributed on an "AS IS" BASIS,
11
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
 * See the License for the specific language governing permissions and
13
 * limitations under the License.
14
 */
15

16
import { getObservableTarget } from "@koalaui/compat"
17

18
/**
19
 * @internal
20
 */
21
export interface Observable {
22
    onAccess(): void
23
    onModify(): void
24
}
25

26
/**
27
 * @internal
28
 */
29
export class ObservableHandler implements Observable {
30
    private static handlers: WeakMap<Object, ObservableHandler> | undefined = undefined
31

32
    private observables = new Set<Observable>()
33
    private _modified = false
34

35
    onAccess(): void {
36
        if (this.observables.size > 0) {
37
            const it = this.observables.keys()
38
            while (true) {
39
                const result = it.next()
40
                if (result.done) break
41
                result.value?.onAccess()
42
            }
43
        }
44
    }
45

46
    onModify(): void {
47
        this._modified = true
48
        if (this.observables.size > 0) {
49
            const it = this.observables.keys()
50
            while (true) {
51
                const result = it.next()
52
                if (result.done) break
53
                result.value?.onModify()
54
            }
55
        }
56
    }
57

58
    static dropModified<Value>(value: Value): boolean {
59
        const handler = ObservableHandler.findIfObject(value)
60
        if (handler === undefined) return false
61
        const result = handler._modified
62
        handler._modified = false
63
        return result
64
    }
65

66
    /** Adds the specified `observable` to the handler corresponding to the given `value`. */
67
    static attach<Value>(value: Value, observable: Observable): void {
68
        const handler = ObservableHandler.findIfObject(value)
69
        if (handler !== undefined) handler.observables.add(observable)
70
    }
71

72
    /** Deletes the specified `observable` from the handler corresponding to the given `value`. */
73
    static detach<Value>(value: Value, observable: Observable): void {
74
        const handler = ObservableHandler.findIfObject(value)
75
        if (handler !== undefined) handler.observables.delete(observable)
76
    }
77

78
    /** @returns the handler corresponding to the given `value` if it was installed */
79
    private static findIfObject<Value>(value: Value): ObservableHandler | undefined {
80
        const handlers = ObservableHandler.handlers
81
        return handlers !== undefined && value instanceof Object ? getObservableHandler(handlers, value as Object) : undefined
82
    }
83

84
    /**
85
     * @param value - any non-null object including arrays
86
     * @returns an observable handler or `undefined` if it is not installed
87
     */
88
    static find(value: Object): ObservableHandler | undefined {
89
        const handlers = ObservableHandler.handlers
90
        return handlers !== undefined ? getObservableHandler(handlers, value) : undefined
91
    }
92

93
    /**
94
     * @param value - any non-null object including arrays
95
     * @param observable - a handler to install on this object
96
     * @throws an error if observable handler cannot be installed
97
     */
98
    static installOn(value: Object, observable?: ObservableHandler): void {
99
        let handlers = ObservableHandler.handlers
100
        if (handlers === undefined) {
101
            handlers = new WeakMap<Object, ObservableHandler>()
102
            ObservableHandler.handlers = handlers
103
        }
104
        observable
105
            ? handlers.set(getObservableTarget(value), observable)
106
            : handlers.delete(getObservableTarget(value))
107
    }
108
}
109

110
function getObservableHandler(handlers: WeakMap<Object, ObservableHandler>, value: Object): ObservableHandler | undefined {
111
    const handler = handlers.get(getObservableTarget(value))
112
    return handler === null ? undefined : handler
113
    // because in the WeakMap stub in escompat library
114
    // get mistakenly returns V|null instead of V|undefined
115
}
116

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.