idlize

Форк
0
95 строк · 3.2 Кб
1
/*
2
 * Copyright (c) 2022-2023 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 { className, uint32 } from "@koalaui/common"
17
import { __context, __id } from "../internals"
18
import { IncrementalNode } from "../tree/IncrementalNode"
19

20
/**
21
 * @param create - the node constructor is invoked only once,
22
 *                 then the created node is attached to the hierarchy
23
 * @param update - the node updater is invoked right after the node constructor,
24
 *                 than it can be invoked again if the values of the used states have changed
25
 * @internal
26
 * @memo:intrinsic
27
 */
28
export function NodeAttach<Node extends IncrementalNode>(
29
    create: () => Node,
30
    /** @memo */
31
    update: (node: Node) => void
32
): void {
33
    const scope = __context().scope<void>(__id(), 0, create, undefined, undefined, undefined)
34
    if (scope.unchanged) {
35
        scope.cached
36
    } else try {
37
        update(__context().node as Node)
38
    } finally {
39
        scope.recache()
40
    }
41
}
42

43
/**
44
 * @param kind - expected kind of current node
45
 * @param name - description of a call site to use use in exception
46
 * @returns current node
47
 * @throws Error with the given name if node kind is not expected
48
 * @internal
49
 * @memo:intrinsic
50
 */
51
export function contextNode<T extends IncrementalNode>(kind: uint32 = 1, name?: string): T {
52
    const node = __context().node
53
    if (node?.isKind(kind) == true) return node as T
54
    throw new Error(name
55
        ? (name + " cannot be used in context of " + className(node))
56
        : ("current " + className(node) + " does not contain the specified kind: " + kind)
57
    )
58
}
59

60
/**
61
 * @internal
62
 */
63
export class DataNode<Data> extends IncrementalNode {
64
    private data: Data | undefined = undefined
65

66
    constructor(kind: uint32 = 1) {
67
        super(kind)
68
    }
69

70
    /**
71
     * @memo:intrinsic
72
     */
73
    static attach<Data>(
74
        kind: uint32,
75
        data: Data,
76
        onDataChange?: () => void
77
    ): void {
78
        const scope = __context().scope<void>(__id(), 1, (): IncrementalNode => new DataNode<Data>(kind), undefined, undefined, undefined)
79
        const state = scope.param(0, data, undefined, undefined, undefined)
80
        if (scope.unchanged) {
81
            scope.cached
82
        } else try {
83
            const node = __context().node as DataNode<Data>
84
            if (node.kind != kind) throw new Error("data node kind changed unexpectedly from " + node.kind + " to " + kind)
85
            node.data = state.value as Data // subscribe to the parameter change
86
            onDataChange?.()
87
        } finally {
88
            scope.recache()
89
        }
90
    }
91

92
    static extract<Data>(kind: uint32, node: IncrementalNode): Data | undefined {
93
        return node.isKind(kind) ? (node as DataNode<Data>).data : undefined
94
    }
95
}
96

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

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

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

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