glass-easel 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -0
- package/dist/glass_easel.all.d.ts +1 -0
- package/dist/glass_easel.all.js +2 -0
- package/dist/glass_easel.all.js.map +1 -0
- package/dist/glass_easel.domlike.global.d.ts +1 -0
- package/dist/glass_easel.domlike.global.js +2 -0
- package/dist/glass_easel.domlike.global.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/types/src/backend/backend_protocol.d.ts +119 -0
- package/dist/types/src/backend/backend_protocol.d.ts.map +1 -0
- package/dist/types/src/backend/composed_backend_protocol.d.ts +90 -0
- package/dist/types/src/backend/composed_backend_protocol.d.ts.map +1 -0
- package/dist/types/src/backend/domlike_backend_protocol.d.ts +76 -0
- package/dist/types/src/backend/domlike_backend_protocol.d.ts.map +1 -0
- package/dist/types/src/backend/mode.d.ts +46 -0
- package/dist/types/src/backend/mode.d.ts.map +1 -0
- package/dist/types/src/backend/suggested_backend_protocol.d.ts +30 -0
- package/dist/types/src/backend/suggested_backend_protocol.d.ts.map +1 -0
- package/dist/types/src/behavior.d.ts +428 -0
- package/dist/types/src/behavior.d.ts.map +1 -0
- package/dist/types/src/class_list.d.ts +79 -0
- package/dist/types/src/class_list.d.ts.map +1 -0
- package/dist/types/src/component.d.ts +291 -0
- package/dist/types/src/component.d.ts.map +1 -0
- package/dist/types/src/component_params.d.ts +239 -0
- package/dist/types/src/component_params.d.ts.map +1 -0
- package/dist/types/src/component_space.d.ts +164 -0
- package/dist/types/src/component_space.d.ts.map +1 -0
- package/dist/types/src/data_path.d.ts +5 -0
- package/dist/types/src/data_path.d.ts.map +1 -0
- package/dist/types/src/data_proxy.d.ts +107 -0
- package/dist/types/src/data_proxy.d.ts.map +1 -0
- package/dist/types/src/data_utils.d.ts +3 -0
- package/dist/types/src/data_utils.d.ts.map +1 -0
- package/dist/types/src/element.d.ts +275 -0
- package/dist/types/src/element.d.ts.map +1 -0
- package/dist/types/src/element_iterator.d.ts +43 -0
- package/dist/types/src/element_iterator.d.ts.map +1 -0
- package/dist/types/src/event.d.ts +104 -0
- package/dist/types/src/event.d.ts.map +1 -0
- package/dist/types/src/external_shadow_tree.d.ts +20 -0
- package/dist/types/src/external_shadow_tree.d.ts.map +1 -0
- package/dist/types/src/func_arr.d.ts +39 -0
- package/dist/types/src/func_arr.d.ts.map +1 -0
- package/dist/types/src/global_options.d.ts +111 -0
- package/dist/types/src/global_options.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +43 -0
- package/dist/types/src/index.d.ts.map +1 -0
- package/dist/types/src/mutation_observer.d.ts +79 -0
- package/dist/types/src/mutation_observer.d.ts.map +1 -0
- package/dist/types/src/native_node.d.ts +8 -0
- package/dist/types/src/native_node.d.ts.map +1 -0
- package/dist/types/src/node.d.ts +49 -0
- package/dist/types/src/node.d.ts.map +1 -0
- package/dist/types/src/relation.d.ts +47 -0
- package/dist/types/src/relation.d.ts.map +1 -0
- package/dist/types/src/render.d.ts +3 -0
- package/dist/types/src/render.d.ts.map +1 -0
- package/dist/types/src/selector.d.ts +32 -0
- package/dist/types/src/selector.d.ts.map +1 -0
- package/dist/types/src/shadow_root.d.ts +136 -0
- package/dist/types/src/shadow_root.d.ts.map +1 -0
- package/dist/types/src/template_engine.d.ts +18 -0
- package/dist/types/src/template_engine.d.ts.map +1 -0
- package/dist/types/src/text_node.d.ts +32 -0
- package/dist/types/src/text_node.d.ts.map +1 -0
- package/dist/types/src/tmpl/index.d.ts +18 -0
- package/dist/types/src/tmpl/index.d.ts.map +1 -0
- package/dist/types/src/tmpl/native_rendering.d.ts +45 -0
- package/dist/types/src/tmpl/native_rendering.d.ts.map +1 -0
- package/dist/types/src/tmpl/proc_gen_wrapper.d.ts +80 -0
- package/dist/types/src/tmpl/proc_gen_wrapper.d.ts.map +1 -0
- package/dist/types/src/tmpl/proc_gen_wrapper_dom.d.ts +50 -0
- package/dist/types/src/tmpl/proc_gen_wrapper_dom.d.ts.map +1 -0
- package/dist/types/src/tmpl/range_list_diff.d.ts +19 -0
- package/dist/types/src/tmpl/range_list_diff.d.ts.map +1 -0
- package/dist/types/src/trait_behaviors.d.ts +38 -0
- package/dist/types/src/trait_behaviors.d.ts.map +1 -0
- package/dist/types/src/virtual_node.d.ts +10 -0
- package/dist/types/src/virtual_node.d.ts.map +1 -0
- package/dist/types/tests/backend/domlike.test.d.ts +2 -0
- package/dist/types/tests/backend/domlike.test.d.ts.map +1 -0
- package/dist/types/tests/base/env.d.ts +29 -0
- package/dist/types/tests/base/env.d.ts.map +1 -0
- package/dist/types/tests/base/match.d.ts +9 -0
- package/dist/types/tests/base/match.d.ts.map +1 -0
- package/dist/types/tests/core/backend.test.d.ts +2 -0
- package/dist/types/tests/core/backend.test.d.ts.map +1 -0
- package/dist/types/tests/core/behavior.test.d.ts +2 -0
- package/dist/types/tests/core/behavior.test.d.ts.map +1 -0
- package/dist/types/tests/core/component_space.test.d.ts +2 -0
- package/dist/types/tests/core/component_space.test.d.ts.map +1 -0
- package/dist/types/tests/core/data_update.test.d.ts +2 -0
- package/dist/types/tests/core/data_update.test.d.ts.map +1 -0
- package/dist/types/tests/core/misc.test.d.ts +2 -0
- package/dist/types/tests/core/misc.test.d.ts.map +1 -0
- package/dist/types/tests/core/placeholder.test.d.ts +2 -0
- package/dist/types/tests/core/placeholder.test.d.ts.map +1 -0
- package/dist/types/tests/core/slot.test.d.ts +2 -0
- package/dist/types/tests/core/slot.test.d.ts.map +1 -0
- package/dist/types/tests/core/trait_behaviors.test.d.ts +2 -0
- package/dist/types/tests/core/trait_behaviors.test.d.ts.map +1 -0
- package/dist/types/tests/tmpl/binding_map.test.d.ts +2 -0
- package/dist/types/tests/tmpl/binding_map.test.d.ts.map +1 -0
- package/dist/types/tests/tmpl/event.test.d.ts +2 -0
- package/dist/types/tests/tmpl/event.test.d.ts.map +1 -0
- package/dist/types/tests/tmpl/expression.test.d.ts +2 -0
- package/dist/types/tests/tmpl/expression.test.d.ts.map +1 -0
- package/dist/types/tests/tmpl/lvalue.test.d.ts +2 -0
- package/dist/types/tests/tmpl/lvalue.test.d.ts.map +1 -0
- package/dist/types/tests/tmpl/native_rendering.test.d.ts +2 -0
- package/dist/types/tests/tmpl/native_rendering.test.d.ts.map +1 -0
- package/dist/types/tests/tmpl/structure.test.d.ts +2 -0
- package/dist/types/tests/tmpl/structure.test.d.ts.map +1 -0
- package/dist/types/tests/types/chaining.test.d.ts +2 -0
- package/dist/types/tests/types/chaining.test.d.ts.map +1 -0
- package/dist/types/tests/types/createElement.test.d.ts +2 -0
- package/dist/types/tests/types/createElement.test.d.ts.map +1 -0
- package/dist/types/tests/types/definition.test.d.ts +2 -0
- package/dist/types/tests/types/definition.test.d.ts.map +1 -0
- package/guide/zh_CN/advanced/binding_map_update.md +32 -0
- package/guide/zh_CN/advanced/build_args.md +28 -0
- package/guide/zh_CN/advanced/component_filter.md +70 -0
- package/guide/zh_CN/advanced/component_space.md +124 -0
- package/guide/zh_CN/advanced/custom_backend.md +53 -0
- package/guide/zh_CN/advanced/error_listener.md +32 -0
- package/guide/zh_CN/advanced/external_component.md +73 -0
- package/guide/zh_CN/advanced/template_engine.md +61 -0
- package/guide/zh_CN/appendix/backend_protocol.md +501 -0
- package/guide/zh_CN/appendix/list_diff_algorithm.md +406 -0
- package/guide/zh_CN/basic/beginning.md +94 -0
- package/guide/zh_CN/basic/component.md +156 -0
- package/guide/zh_CN/basic/event.md +169 -0
- package/guide/zh_CN/basic/lifetime.md +66 -0
- package/guide/zh_CN/basic/method.md +62 -0
- package/guide/zh_CN/basic/template.md +135 -0
- package/guide/zh_CN/data_management/advanced_update.md +170 -0
- package/guide/zh_CN/data_management/data_deep_copy.md +157 -0
- package/guide/zh_CN/data_management/data_observer.md +154 -0
- package/guide/zh_CN/data_management/property_early_init.md +31 -0
- package/guide/zh_CN/data_management/pure_data_pattern.md +21 -0
- package/guide/zh_CN/index.md +93 -0
- package/guide/zh_CN/interaction/behavior.md +52 -0
- package/guide/zh_CN/interaction/component_path.md +37 -0
- package/guide/zh_CN/interaction/generic.md +73 -0
- package/guide/zh_CN/interaction/placeholder.md +40 -0
- package/guide/zh_CN/interaction/relation.md +151 -0
- package/guide/zh_CN/interaction/slot.md +137 -0
- package/guide/zh_CN/interaction/template_import.md +94 -0
- package/guide/zh_CN/interaction/trait_behavior.md +117 -0
- package/guide/zh_CN/styling/external_class.md +46 -0
- package/guide/zh_CN/styling/style_isolation.md +54 -0
- package/guide/zh_CN/styling/virtual_host.md +52 -0
- package/guide/zh_CN/tree/element_iterator.md +54 -0
- package/guide/zh_CN/tree/mutation_observer.md +52 -0
- package/guide/zh_CN/tree/node_tree.md +142 -0
- package/guide/zh_CN/tree/node_tree_modification.md +78 -0
- package/guide/zh_CN/tree/selector.md +66 -0
- package/jest.config.js +6 -0
- package/jest.dts.config.js +9 -0
- package/jest.unit.config.js +14 -0
- package/package.json +28 -0
- package/src/backend/backend_protocol.ts +313 -0
- package/src/backend/composed_backend_protocol.ts +252 -0
- package/src/backend/domlike_backend_protocol.ts +370 -0
- package/src/backend/mode.ts +51 -0
- package/src/backend/suggested_backend_protocol.ts +83 -0
- package/src/behavior.ts +1655 -0
- package/src/bootstrap_dom_dev.js +22 -0
- package/src/class_list.ts +376 -0
- package/src/component.ts +1309 -0
- package/src/component_params.ts +461 -0
- package/src/component_space.ts +547 -0
- package/src/data_path.ts +225 -0
- package/src/data_proxy.ts +670 -0
- package/src/data_utils.ts +50 -0
- package/src/element.ts +1966 -0
- package/src/element_iterator.ts +158 -0
- package/src/event.ts +401 -0
- package/src/external_shadow_tree.ts +27 -0
- package/src/func_arr.ts +198 -0
- package/src/global_options.ts +242 -0
- package/src/index.ts +187 -0
- package/src/mutation_observer.ts +252 -0
- package/src/native_node.ts +74 -0
- package/src/node.ts +174 -0
- package/src/relation.ts +380 -0
- package/src/render.ts +25 -0
- package/src/selector.ts +218 -0
- package/src/shadow_root.ts +766 -0
- package/src/template_engine.ts +45 -0
- package/src/text_node.ts +149 -0
- package/src/tmpl/index.ts +199 -0
- package/src/tmpl/native_rendering.ts +175 -0
- package/src/tmpl/proc_gen_wrapper.ts +954 -0
- package/src/tmpl/proc_gen_wrapper_dom.ts +230 -0
- package/src/tmpl/range_list_diff.ts +443 -0
- package/src/trait_behaviors.ts +51 -0
- package/src/virtual_node.ts +51 -0
- package/tests/backend/domlike.test.ts +254 -0
- package/tests/base/env.ts +78 -0
- package/tests/base/match.ts +185 -0
- package/tests/core/backend.test.ts +144 -0
- package/tests/core/behavior.test.ts +546 -0
- package/tests/core/component_space.test.ts +212 -0
- package/tests/core/data_update.test.ts +461 -0
- package/tests/core/misc.test.ts +339 -0
- package/tests/core/placeholder.test.ts +180 -0
- package/tests/core/slot.test.ts +1495 -0
- package/tests/core/trait_behaviors.test.ts +153 -0
- package/tests/legacy/README.md +3 -0
- package/tests/legacy/behavior.test.js +293 -0
- package/tests/legacy/component.test.js +1247 -0
- package/tests/legacy/data_path.test.js +149 -0
- package/tests/legacy/data_proxy.test.js +759 -0
- package/tests/legacy/element_iterator.test.js +148 -0
- package/tests/legacy/event.test.js +849 -0
- package/tests/legacy/external.test.js +510 -0
- package/tests/legacy/extra_info.test.js +109 -0
- package/tests/legacy/generics.test.js +176 -0
- package/tests/legacy/mutation_observer.test.js +210 -0
- package/tests/legacy/relation.test.js +517 -0
- package/tests/legacy/selector.test.js +263 -0
- package/tests/legacy/slot.test.js +915 -0
- package/tests/legacy/virtual.test.js +394 -0
- package/tests/tmpl/binding_map.test.ts +208 -0
- package/tests/tmpl/event.test.ts +206 -0
- package/tests/tmpl/expression.test.ts +429 -0
- package/tests/tmpl/lvalue.test.ts +160 -0
- package/tests/tmpl/native_rendering.test.ts +155 -0
- package/tests/tmpl/structure.test.ts +998 -0
- package/tests/types/chaining.test.ts +614 -0
- package/tests/types/createElement.test.ts +82 -0
- package/tests/types/definition.test.ts +442 -0
- package/tsconfig.json +11 -0
- package/webpack.config.js +270 -0
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Element,
|
|
3
|
+
Node,
|
|
4
|
+
TextNode,
|
|
5
|
+
} from '.'
|
|
6
|
+
import {
|
|
7
|
+
FuncArr,
|
|
8
|
+
} from './func_arr'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* What the observer will listen
|
|
12
|
+
*/
|
|
13
|
+
export type MutationObserverOptions = {
|
|
14
|
+
/** Attribute changes, including property, id, slot, and class changes */
|
|
15
|
+
properties: boolean
|
|
16
|
+
/** Child nodes changes */
|
|
17
|
+
childList: boolean
|
|
18
|
+
/** Text content changes */
|
|
19
|
+
characterData: boolean
|
|
20
|
+
/** Enable property, childList, and characterData changes in subtree */
|
|
21
|
+
subtree: boolean
|
|
22
|
+
/** Attached status changes */
|
|
23
|
+
attachStatus: boolean
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export type MutationObserverAttrEvent = {
|
|
27
|
+
type: 'properties',
|
|
28
|
+
target: Element,
|
|
29
|
+
propertyName?: string,
|
|
30
|
+
attributeName?: string,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export type MutationObserverTextEvent = {
|
|
34
|
+
type: 'characterData',
|
|
35
|
+
target: TextNode,
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export type MutationObserverChildEvent = {
|
|
39
|
+
type: 'childList',
|
|
40
|
+
target: Node,
|
|
41
|
+
addedNodes?: Node[],
|
|
42
|
+
removedNodes?: Node[],
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export type MutationObserverAttachEvent = {
|
|
46
|
+
type: 'attachStatus',
|
|
47
|
+
target: Element,
|
|
48
|
+
status: 'attached' | 'detached',
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export type MutationObserverEvent =
|
|
52
|
+
MutationObserverAttrEvent
|
|
53
|
+
| MutationObserverTextEvent
|
|
54
|
+
| MutationObserverChildEvent
|
|
55
|
+
| MutationObserverAttachEvent
|
|
56
|
+
|
|
57
|
+
export type MutationObserverListener<T> = (this: Element, ev: T) => void
|
|
58
|
+
|
|
59
|
+
export class MutationObserverTarget {
|
|
60
|
+
private _$bindedElement: Element
|
|
61
|
+
private _$subtreeObserversCount = 0
|
|
62
|
+
attrObservers: FuncArr<MutationObserverListener<MutationObserverAttrEvent>> | null = null
|
|
63
|
+
textObservers: FuncArr<MutationObserverListener<MutationObserverTextEvent>> | null = null
|
|
64
|
+
childObservers: FuncArr<MutationObserverListener<MutationObserverChildEvent>> | null = null
|
|
65
|
+
attachObservers: FuncArr<MutationObserverListener<MutationObserverAttachEvent>> | null = null
|
|
66
|
+
|
|
67
|
+
constructor(bindedElement: Element) {
|
|
68
|
+
this._$bindedElement = bindedElement
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
attachChild(child: Element) {
|
|
72
|
+
if (!child._$mutationObserverTarget) {
|
|
73
|
+
child._$mutationObserverTarget = new MutationObserverTarget(child)
|
|
74
|
+
}
|
|
75
|
+
if (this._$subtreeObserversCount > 0) {
|
|
76
|
+
child._$mutationObserverTarget.updateSubtreeCount(this._$subtreeObserversCount)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
detachChild(child: Element) {
|
|
81
|
+
if (child._$mutationObserverTarget) {
|
|
82
|
+
child._$mutationObserverTarget.updateSubtreeCount(-this._$subtreeObserversCount)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
updateSubtreeCount(diff: number) {
|
|
87
|
+
this._$subtreeObserversCount += diff
|
|
88
|
+
const children = this._$bindedElement.childNodes
|
|
89
|
+
children.forEach((child) => {
|
|
90
|
+
if (child instanceof Element) {
|
|
91
|
+
if (!child._$mutationObserverTarget) {
|
|
92
|
+
child._$mutationObserverTarget = new MutationObserverTarget(child)
|
|
93
|
+
}
|
|
94
|
+
child._$mutationObserverTarget.updateSubtreeCount(diff)
|
|
95
|
+
}
|
|
96
|
+
})
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
hasSubtreeListeners(): boolean {
|
|
100
|
+
return this._$subtreeObserversCount > 0
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
static callAttrObservers(node: Element, eventObj: MutationObserverAttrEvent) {
|
|
104
|
+
let cur = node
|
|
105
|
+
do {
|
|
106
|
+
const target = cur._$mutationObserverTarget
|
|
107
|
+
target?.attrObservers?.call(cur, [eventObj])
|
|
108
|
+
const next = cur.parentNode
|
|
109
|
+
if (!next) break
|
|
110
|
+
cur = next
|
|
111
|
+
if (!cur._$mutationObserverTarget) break
|
|
112
|
+
} while (cur._$mutationObserverTarget._$subtreeObserversCount > 0)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
static callTextObservers(textNode: TextNode, eventObj: MutationObserverTextEvent) {
|
|
116
|
+
let cur = textNode.parentNode
|
|
117
|
+
while (cur) {
|
|
118
|
+
const target = cur._$mutationObserverTarget
|
|
119
|
+
if (!target || target._$subtreeObserversCount === 0) break
|
|
120
|
+
target.textObservers?.call(cur, [eventObj])
|
|
121
|
+
cur = cur.parentNode
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
static callChildObservers(node: Element, eventObj: MutationObserverChildEvent) {
|
|
126
|
+
let cur = node
|
|
127
|
+
do {
|
|
128
|
+
const target = cur._$mutationObserverTarget
|
|
129
|
+
target?.childObservers?.call(cur, [eventObj])
|
|
130
|
+
const next = cur.parentNode
|
|
131
|
+
if (!next) break
|
|
132
|
+
cur = next
|
|
133
|
+
if (!cur._$mutationObserverTarget) break
|
|
134
|
+
} while (cur._$mutationObserverTarget._$subtreeObserversCount > 0)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
static callAttachObservers(node: Element, eventObj: MutationObserverAttachEvent) {
|
|
138
|
+
const target = node._$mutationObserverTarget
|
|
139
|
+
target?.attachObservers?.call(node, [eventObj])
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* An observer that can observe shadow tree changes
|
|
145
|
+
*
|
|
146
|
+
* Like DOM MutationObserver,
|
|
147
|
+
* this observer can observe attributes, text content, and child nodes changes.
|
|
148
|
+
* It can optionally observe changes in a subtree.
|
|
149
|
+
* Further more, it can listen attached/detached events on an element.
|
|
150
|
+
*/
|
|
151
|
+
export class MutationObserver {
|
|
152
|
+
private _$listener: MutationObserverListener<MutationObserverEvent> | null
|
|
153
|
+
private _$normalizedListener: MutationObserverListener<MutationObserverEvent> | null
|
|
154
|
+
private _$subtreeListenersCount = 0
|
|
155
|
+
private _$bindedFuncArrs: FuncArr<MutationObserverListener<MutationObserverEvent>>[] = []
|
|
156
|
+
private _$bindedTarget: MutationObserverTarget | null = null
|
|
157
|
+
|
|
158
|
+
constructor(
|
|
159
|
+
listener: (ev: MutationObserverEvent) => void,
|
|
160
|
+
) {
|
|
161
|
+
this._$listener = listener
|
|
162
|
+
this._$normalizedListener = null
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
static create(
|
|
166
|
+
listener: (ev: MutationObserverEvent) => void,
|
|
167
|
+
): MutationObserver {
|
|
168
|
+
return new MutationObserver(listener)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/** Start observation */
|
|
172
|
+
observe(
|
|
173
|
+
targetElement: Element,
|
|
174
|
+
options: MutationObserverOptions = {
|
|
175
|
+
properties: false,
|
|
176
|
+
childList: false,
|
|
177
|
+
characterData: false,
|
|
178
|
+
subtree: false,
|
|
179
|
+
attachStatus: false,
|
|
180
|
+
},
|
|
181
|
+
) {
|
|
182
|
+
const listener = this._$listener
|
|
183
|
+
if (!listener) {
|
|
184
|
+
throw new Error('A MutationObserver can only observe once')
|
|
185
|
+
}
|
|
186
|
+
let target: MutationObserverTarget
|
|
187
|
+
if (targetElement._$mutationObserverTarget) {
|
|
188
|
+
target = targetElement._$mutationObserverTarget
|
|
189
|
+
} else {
|
|
190
|
+
target = new MutationObserverTarget(targetElement)
|
|
191
|
+
targetElement._$mutationObserverTarget = target
|
|
192
|
+
}
|
|
193
|
+
this._$listener = null
|
|
194
|
+
const cb = (
|
|
195
|
+
options.subtree
|
|
196
|
+
? listener
|
|
197
|
+
: function noSubtreeListener(this: Node, ev: MutationObserverEvent) {
|
|
198
|
+
// this might be TextNode, but do the same as Element
|
|
199
|
+
if (ev.target === this) listener.call(this as Element, ev)
|
|
200
|
+
}
|
|
201
|
+
)
|
|
202
|
+
this._$normalizedListener = cb
|
|
203
|
+
this._$bindedTarget = target
|
|
204
|
+
if (options.properties) {
|
|
205
|
+
if (!target.attrObservers) target.attrObservers = new FuncArr()
|
|
206
|
+
target.attrObservers.add(cb)
|
|
207
|
+
this._$bindedFuncArrs.push(
|
|
208
|
+
target.attrObservers as FuncArr<MutationObserverListener<MutationObserverEvent>>,
|
|
209
|
+
)
|
|
210
|
+
this._$subtreeListenersCount += 1
|
|
211
|
+
}
|
|
212
|
+
if (options.childList) {
|
|
213
|
+
if (!target.childObservers) target.childObservers = new FuncArr()
|
|
214
|
+
target.childObservers.add(cb)
|
|
215
|
+
this._$bindedFuncArrs.push(
|
|
216
|
+
target.childObservers as FuncArr<MutationObserverListener<MutationObserverEvent>>,
|
|
217
|
+
)
|
|
218
|
+
this._$subtreeListenersCount += 1
|
|
219
|
+
}
|
|
220
|
+
if (options.characterData) {
|
|
221
|
+
if (!target.textObservers) target.textObservers = new FuncArr()
|
|
222
|
+
target.textObservers.add(cb)
|
|
223
|
+
this._$bindedFuncArrs.push(
|
|
224
|
+
target.textObservers as FuncArr<MutationObserverListener<MutationObserverEvent>>,
|
|
225
|
+
)
|
|
226
|
+
this._$subtreeListenersCount += 1
|
|
227
|
+
}
|
|
228
|
+
if (options.subtree) {
|
|
229
|
+
target.updateSubtreeCount(this._$subtreeListenersCount)
|
|
230
|
+
}
|
|
231
|
+
if (options.attachStatus) {
|
|
232
|
+
if (!target.attachObservers) target.attachObservers = new FuncArr()
|
|
233
|
+
target.attachObservers.add(cb)
|
|
234
|
+
this._$bindedFuncArrs.push(
|
|
235
|
+
target.attachObservers as FuncArr<MutationObserverListener<MutationObserverEvent>>,
|
|
236
|
+
)
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/** End observation */
|
|
241
|
+
disconnect() {
|
|
242
|
+
this._$bindedTarget?.updateSubtreeCount(-this._$subtreeListenersCount)
|
|
243
|
+
const arr = this._$bindedFuncArrs
|
|
244
|
+
this._$bindedFuncArrs = []
|
|
245
|
+
const nl = this._$normalizedListener
|
|
246
|
+
if (nl) {
|
|
247
|
+
arr.forEach((funcArr) => {
|
|
248
|
+
funcArr.remove(nl)
|
|
249
|
+
})
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import * as backend from './backend/backend_protocol'
|
|
2
|
+
import * as composedBackend from './backend/composed_backend_protocol'
|
|
3
|
+
import * as domlikeBackend from './backend/domlike_backend_protocol'
|
|
4
|
+
import {
|
|
5
|
+
globalOptions,
|
|
6
|
+
} from './global_options'
|
|
7
|
+
import {
|
|
8
|
+
ClassList,
|
|
9
|
+
} from './class_list'
|
|
10
|
+
import {
|
|
11
|
+
Element,
|
|
12
|
+
} from './element'
|
|
13
|
+
import {
|
|
14
|
+
ShadowRoot,
|
|
15
|
+
} from './shadow_root'
|
|
16
|
+
import {
|
|
17
|
+
GeneralBackendElement,
|
|
18
|
+
} from '.'
|
|
19
|
+
import {
|
|
20
|
+
BM,
|
|
21
|
+
BackendMode,
|
|
22
|
+
} from './backend/mode'
|
|
23
|
+
|
|
24
|
+
export class NativeNode extends Element {
|
|
25
|
+
is: string
|
|
26
|
+
|
|
27
|
+
constructor() {
|
|
28
|
+
throw new Error('Element cannot be constructed directly')
|
|
29
|
+
// eslint-disable-next-line no-unreachable
|
|
30
|
+
super()
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
static create(
|
|
34
|
+
tagName: string,
|
|
35
|
+
owner: ShadowRoot,
|
|
36
|
+
): NativeNode {
|
|
37
|
+
const node = Object.create(NativeNode.prototype) as NativeNode
|
|
38
|
+
node.is = tagName
|
|
39
|
+
let backendElement: GeneralBackendElement | null
|
|
40
|
+
if (BM.DOMLIKE || (BM.DYNAMIC && owner.getBackendMode() === BackendMode.Domlike)) {
|
|
41
|
+
backendElement = (owner._$nodeTreeContext as domlikeBackend.Context)
|
|
42
|
+
.document.createElement(tagName)
|
|
43
|
+
} else if (BM.SHADOW || (BM.DYNAMIC && owner.getBackendMode() === BackendMode.Shadow)) {
|
|
44
|
+
const backend = owner._$backendShadowRoot
|
|
45
|
+
backendElement = backend?.createElement(tagName) || null
|
|
46
|
+
} else {
|
|
47
|
+
const backend = owner._$nodeTreeContext as composedBackend.Context
|
|
48
|
+
backendElement = backend.createElement(tagName)
|
|
49
|
+
}
|
|
50
|
+
node._$initialize(false, backendElement, owner)
|
|
51
|
+
node.classList = new ClassList(node, null)
|
|
52
|
+
if (owner && backendElement) {
|
|
53
|
+
const styleScope = owner.getHostNode()._$definition._$options.styleScope
|
|
54
|
+
if (styleScope) {
|
|
55
|
+
if (!(BM.DOMLIKE || (BM.DYNAMIC && owner.getBackendMode() === BackendMode.Domlike))) {
|
|
56
|
+
(backendElement as backend.Element | composedBackend.Element).setStyleScope(styleScope)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (globalOptions.writeExtraInfoToAttr) {
|
|
60
|
+
const prefix = owner.getHostNode()
|
|
61
|
+
._$behavior.ownerSpace?.styleScopeManager.queryName(styleScope)
|
|
62
|
+
if (prefix) {
|
|
63
|
+
backendElement.setAttribute('exparser:info-class-prefix', `${prefix}--`)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (!(BM.DOMLIKE || (BM.DYNAMIC && owner.getBackendMode() === BackendMode.Domlike))) {
|
|
68
|
+
if (backendElement) {
|
|
69
|
+
(backendElement as backend.Element | composedBackend.Element).associateValue(node)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return node
|
|
73
|
+
}
|
|
74
|
+
}
|
package/src/node.ts
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import * as backend from './backend/backend_protocol'
|
|
2
|
+
import * as composedBackend from './backend/composed_backend_protocol'
|
|
3
|
+
import * as domlikeBackend from './backend/domlike_backend_protocol'
|
|
4
|
+
import * as suggestedBackend from './backend/suggested_backend_protocol'
|
|
5
|
+
import {
|
|
6
|
+
TextNode,
|
|
7
|
+
} from './text_node'
|
|
8
|
+
import {
|
|
9
|
+
Element,
|
|
10
|
+
} from './element'
|
|
11
|
+
import {
|
|
12
|
+
VirtualNode,
|
|
13
|
+
} from './virtual_node'
|
|
14
|
+
import {
|
|
15
|
+
Component,
|
|
16
|
+
ComponentDefinition,
|
|
17
|
+
} from './component'
|
|
18
|
+
import {
|
|
19
|
+
NativeNode,
|
|
20
|
+
} from './native_node'
|
|
21
|
+
import {
|
|
22
|
+
DataList,
|
|
23
|
+
PropertyList,
|
|
24
|
+
MethodList,
|
|
25
|
+
ComponentInstance,
|
|
26
|
+
} from './component_params'
|
|
27
|
+
|
|
28
|
+
export type GeneralBackendContext = (
|
|
29
|
+
| backend.Context
|
|
30
|
+
| composedBackend.Context
|
|
31
|
+
| domlikeBackend.Context
|
|
32
|
+
) &
|
|
33
|
+
Partial<suggestedBackend.Context>
|
|
34
|
+
export type GeneralBackendElement = (
|
|
35
|
+
| backend.Element
|
|
36
|
+
| composedBackend.Element
|
|
37
|
+
| domlikeBackend.Element
|
|
38
|
+
) &
|
|
39
|
+
Partial<suggestedBackend.Element>
|
|
40
|
+
|
|
41
|
+
export type Node = TextNode | Element
|
|
42
|
+
|
|
43
|
+
export interface NodeCast {
|
|
44
|
+
/**
|
|
45
|
+
* Cast a node to a text node
|
|
46
|
+
*
|
|
47
|
+
* Returns `null` if the element is not a text node.
|
|
48
|
+
*/
|
|
49
|
+
asTextNode(): TextNode | null
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Cast a node to an element (native node, virtual node, or component node)
|
|
53
|
+
*
|
|
54
|
+
* Returns `null` if the element is not a text node.
|
|
55
|
+
*/
|
|
56
|
+
asElement(): Element | null
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Cast an element to a native node
|
|
60
|
+
*
|
|
61
|
+
* Returns `null` if the element is not a native node.
|
|
62
|
+
*/
|
|
63
|
+
asNativeNode(): NativeNode | null
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Cast an element to a virtual node
|
|
67
|
+
*
|
|
68
|
+
* Returns `null` if the element is not a virtual node.
|
|
69
|
+
*/
|
|
70
|
+
asVirtualNode(): VirtualNode | null
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Cast an element to the instance of the specified component
|
|
74
|
+
*
|
|
75
|
+
* Returns `null` if the element is not the instance of the specified component.
|
|
76
|
+
*/
|
|
77
|
+
asInstanceOf<
|
|
78
|
+
UData extends DataList,
|
|
79
|
+
UProperty extends PropertyList,
|
|
80
|
+
UMethod extends MethodList,
|
|
81
|
+
>(
|
|
82
|
+
componentDefinition: ComponentDefinition<UData, UProperty, UMethod>,
|
|
83
|
+
): ComponentInstance<UData, UProperty, UMethod> | null
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const dumpAttributesToString = (elem: Element): string => {
|
|
87
|
+
let ret = ''
|
|
88
|
+
if (elem instanceof Element) {
|
|
89
|
+
if (elem._$slotName !== null) ret += ` (slot) name="${elem._$slotName}"`
|
|
90
|
+
if (elem.id) ret += ` id="${elem.id}"`
|
|
91
|
+
if (elem.slot) ret += ` slot="${elem.slot}"`
|
|
92
|
+
const nodeClass = elem.class
|
|
93
|
+
if (nodeClass) ret += ` class="${nodeClass}"`
|
|
94
|
+
const style = elem.style
|
|
95
|
+
if (style) ret += ` style="${elem.style}"`
|
|
96
|
+
}
|
|
97
|
+
if (elem instanceof VirtualNode) {
|
|
98
|
+
// empty
|
|
99
|
+
} else if (elem instanceof Component) {
|
|
100
|
+
Component.listProperties(elem).forEach((propName) => {
|
|
101
|
+
ret += ` ${propName}="${String((elem.data as DataList)[propName])}"`
|
|
102
|
+
})
|
|
103
|
+
} else {
|
|
104
|
+
elem.attributes.forEach((attr) => {
|
|
105
|
+
ret += ` ${attr.name}="${String(attr.value)}"`
|
|
106
|
+
})
|
|
107
|
+
}
|
|
108
|
+
return ret
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export const dumpSingleElementToString = (elem: any) => {
|
|
112
|
+
if (elem instanceof Element) {
|
|
113
|
+
let tagName: string
|
|
114
|
+
if (elem instanceof VirtualNode) {
|
|
115
|
+
tagName = `(virtual):${elem.is}`
|
|
116
|
+
} else if (elem instanceof Component) {
|
|
117
|
+
tagName = `${elem.tagName}:${elem.is}`
|
|
118
|
+
} else if (elem instanceof NativeNode) {
|
|
119
|
+
tagName = elem.is
|
|
120
|
+
} else {
|
|
121
|
+
tagName = '(unknown)'
|
|
122
|
+
}
|
|
123
|
+
return `<${tagName}${dumpAttributesToString(elem)}>`
|
|
124
|
+
}
|
|
125
|
+
if (elem instanceof TextNode) {
|
|
126
|
+
return elem.textContent.trim()
|
|
127
|
+
}
|
|
128
|
+
if (elem === null) {
|
|
129
|
+
return '<(null)>'
|
|
130
|
+
}
|
|
131
|
+
if (elem === undefined) {
|
|
132
|
+
return '<(undefined)>'
|
|
133
|
+
}
|
|
134
|
+
return '<(unknown)>'
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export const dumpElementToString = (elem: any, composed: boolean, tabDepth = 0) => {
|
|
138
|
+
let linePrefix = ''
|
|
139
|
+
for (let i = tabDepth; i; i -= 1) {
|
|
140
|
+
linePrefix += ' '
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
let ret = linePrefix + dumpSingleElementToString(elem)
|
|
144
|
+
let isExternal = false
|
|
145
|
+
|
|
146
|
+
if (elem instanceof Element) {
|
|
147
|
+
if (elem instanceof Component) {
|
|
148
|
+
isExternal = elem.getComponentOptions().externalComponent
|
|
149
|
+
}
|
|
150
|
+
if (composed) {
|
|
151
|
+
if (isExternal) {
|
|
152
|
+
ret += `\n${linePrefix} <(external)>`
|
|
153
|
+
elem.childNodes.forEach((node) => {
|
|
154
|
+
ret += `\n${dumpElementToString(node, composed, tabDepth + 2)}`
|
|
155
|
+
})
|
|
156
|
+
} else {
|
|
157
|
+
elem.forEachComposedChild((node) => {
|
|
158
|
+
ret += `\n${dumpElementToString(node, composed, tabDepth + 1)}`
|
|
159
|
+
})
|
|
160
|
+
}
|
|
161
|
+
} else {
|
|
162
|
+
elem.childNodes.forEach((node) => {
|
|
163
|
+
ret += `\n${dumpElementToString(node, composed, tabDepth + 1)}`
|
|
164
|
+
})
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return ret
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export const dumpElement = (elem: any, composed: boolean) => {
|
|
172
|
+
// eslint-disable-next-line no-console
|
|
173
|
+
console.log(dumpElementToString(elem, composed))
|
|
174
|
+
}
|