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.
Files changed (237) hide show
  1. package/README.md +40 -0
  2. package/dist/glass_easel.all.d.ts +1 -0
  3. package/dist/glass_easel.all.js +2 -0
  4. package/dist/glass_easel.all.js.map +1 -0
  5. package/dist/glass_easel.domlike.global.d.ts +1 -0
  6. package/dist/glass_easel.domlike.global.js +2 -0
  7. package/dist/glass_easel.domlike.global.js.map +1 -0
  8. package/dist/index.d.ts +1 -0
  9. package/dist/index.js +1 -0
  10. package/dist/types/src/backend/backend_protocol.d.ts +119 -0
  11. package/dist/types/src/backend/backend_protocol.d.ts.map +1 -0
  12. package/dist/types/src/backend/composed_backend_protocol.d.ts +90 -0
  13. package/dist/types/src/backend/composed_backend_protocol.d.ts.map +1 -0
  14. package/dist/types/src/backend/domlike_backend_protocol.d.ts +76 -0
  15. package/dist/types/src/backend/domlike_backend_protocol.d.ts.map +1 -0
  16. package/dist/types/src/backend/mode.d.ts +46 -0
  17. package/dist/types/src/backend/mode.d.ts.map +1 -0
  18. package/dist/types/src/backend/suggested_backend_protocol.d.ts +30 -0
  19. package/dist/types/src/backend/suggested_backend_protocol.d.ts.map +1 -0
  20. package/dist/types/src/behavior.d.ts +428 -0
  21. package/dist/types/src/behavior.d.ts.map +1 -0
  22. package/dist/types/src/class_list.d.ts +79 -0
  23. package/dist/types/src/class_list.d.ts.map +1 -0
  24. package/dist/types/src/component.d.ts +291 -0
  25. package/dist/types/src/component.d.ts.map +1 -0
  26. package/dist/types/src/component_params.d.ts +239 -0
  27. package/dist/types/src/component_params.d.ts.map +1 -0
  28. package/dist/types/src/component_space.d.ts +164 -0
  29. package/dist/types/src/component_space.d.ts.map +1 -0
  30. package/dist/types/src/data_path.d.ts +5 -0
  31. package/dist/types/src/data_path.d.ts.map +1 -0
  32. package/dist/types/src/data_proxy.d.ts +107 -0
  33. package/dist/types/src/data_proxy.d.ts.map +1 -0
  34. package/dist/types/src/data_utils.d.ts +3 -0
  35. package/dist/types/src/data_utils.d.ts.map +1 -0
  36. package/dist/types/src/element.d.ts +275 -0
  37. package/dist/types/src/element.d.ts.map +1 -0
  38. package/dist/types/src/element_iterator.d.ts +43 -0
  39. package/dist/types/src/element_iterator.d.ts.map +1 -0
  40. package/dist/types/src/event.d.ts +104 -0
  41. package/dist/types/src/event.d.ts.map +1 -0
  42. package/dist/types/src/external_shadow_tree.d.ts +20 -0
  43. package/dist/types/src/external_shadow_tree.d.ts.map +1 -0
  44. package/dist/types/src/func_arr.d.ts +39 -0
  45. package/dist/types/src/func_arr.d.ts.map +1 -0
  46. package/dist/types/src/global_options.d.ts +111 -0
  47. package/dist/types/src/global_options.d.ts.map +1 -0
  48. package/dist/types/src/index.d.ts +43 -0
  49. package/dist/types/src/index.d.ts.map +1 -0
  50. package/dist/types/src/mutation_observer.d.ts +79 -0
  51. package/dist/types/src/mutation_observer.d.ts.map +1 -0
  52. package/dist/types/src/native_node.d.ts +8 -0
  53. package/dist/types/src/native_node.d.ts.map +1 -0
  54. package/dist/types/src/node.d.ts +49 -0
  55. package/dist/types/src/node.d.ts.map +1 -0
  56. package/dist/types/src/relation.d.ts +47 -0
  57. package/dist/types/src/relation.d.ts.map +1 -0
  58. package/dist/types/src/render.d.ts +3 -0
  59. package/dist/types/src/render.d.ts.map +1 -0
  60. package/dist/types/src/selector.d.ts +32 -0
  61. package/dist/types/src/selector.d.ts.map +1 -0
  62. package/dist/types/src/shadow_root.d.ts +136 -0
  63. package/dist/types/src/shadow_root.d.ts.map +1 -0
  64. package/dist/types/src/template_engine.d.ts +18 -0
  65. package/dist/types/src/template_engine.d.ts.map +1 -0
  66. package/dist/types/src/text_node.d.ts +32 -0
  67. package/dist/types/src/text_node.d.ts.map +1 -0
  68. package/dist/types/src/tmpl/index.d.ts +18 -0
  69. package/dist/types/src/tmpl/index.d.ts.map +1 -0
  70. package/dist/types/src/tmpl/native_rendering.d.ts +45 -0
  71. package/dist/types/src/tmpl/native_rendering.d.ts.map +1 -0
  72. package/dist/types/src/tmpl/proc_gen_wrapper.d.ts +80 -0
  73. package/dist/types/src/tmpl/proc_gen_wrapper.d.ts.map +1 -0
  74. package/dist/types/src/tmpl/proc_gen_wrapper_dom.d.ts +50 -0
  75. package/dist/types/src/tmpl/proc_gen_wrapper_dom.d.ts.map +1 -0
  76. package/dist/types/src/tmpl/range_list_diff.d.ts +19 -0
  77. package/dist/types/src/tmpl/range_list_diff.d.ts.map +1 -0
  78. package/dist/types/src/trait_behaviors.d.ts +38 -0
  79. package/dist/types/src/trait_behaviors.d.ts.map +1 -0
  80. package/dist/types/src/virtual_node.d.ts +10 -0
  81. package/dist/types/src/virtual_node.d.ts.map +1 -0
  82. package/dist/types/tests/backend/domlike.test.d.ts +2 -0
  83. package/dist/types/tests/backend/domlike.test.d.ts.map +1 -0
  84. package/dist/types/tests/base/env.d.ts +29 -0
  85. package/dist/types/tests/base/env.d.ts.map +1 -0
  86. package/dist/types/tests/base/match.d.ts +9 -0
  87. package/dist/types/tests/base/match.d.ts.map +1 -0
  88. package/dist/types/tests/core/backend.test.d.ts +2 -0
  89. package/dist/types/tests/core/backend.test.d.ts.map +1 -0
  90. package/dist/types/tests/core/behavior.test.d.ts +2 -0
  91. package/dist/types/tests/core/behavior.test.d.ts.map +1 -0
  92. package/dist/types/tests/core/component_space.test.d.ts +2 -0
  93. package/dist/types/tests/core/component_space.test.d.ts.map +1 -0
  94. package/dist/types/tests/core/data_update.test.d.ts +2 -0
  95. package/dist/types/tests/core/data_update.test.d.ts.map +1 -0
  96. package/dist/types/tests/core/misc.test.d.ts +2 -0
  97. package/dist/types/tests/core/misc.test.d.ts.map +1 -0
  98. package/dist/types/tests/core/placeholder.test.d.ts +2 -0
  99. package/dist/types/tests/core/placeholder.test.d.ts.map +1 -0
  100. package/dist/types/tests/core/slot.test.d.ts +2 -0
  101. package/dist/types/tests/core/slot.test.d.ts.map +1 -0
  102. package/dist/types/tests/core/trait_behaviors.test.d.ts +2 -0
  103. package/dist/types/tests/core/trait_behaviors.test.d.ts.map +1 -0
  104. package/dist/types/tests/tmpl/binding_map.test.d.ts +2 -0
  105. package/dist/types/tests/tmpl/binding_map.test.d.ts.map +1 -0
  106. package/dist/types/tests/tmpl/event.test.d.ts +2 -0
  107. package/dist/types/tests/tmpl/event.test.d.ts.map +1 -0
  108. package/dist/types/tests/tmpl/expression.test.d.ts +2 -0
  109. package/dist/types/tests/tmpl/expression.test.d.ts.map +1 -0
  110. package/dist/types/tests/tmpl/lvalue.test.d.ts +2 -0
  111. package/dist/types/tests/tmpl/lvalue.test.d.ts.map +1 -0
  112. package/dist/types/tests/tmpl/native_rendering.test.d.ts +2 -0
  113. package/dist/types/tests/tmpl/native_rendering.test.d.ts.map +1 -0
  114. package/dist/types/tests/tmpl/structure.test.d.ts +2 -0
  115. package/dist/types/tests/tmpl/structure.test.d.ts.map +1 -0
  116. package/dist/types/tests/types/chaining.test.d.ts +2 -0
  117. package/dist/types/tests/types/chaining.test.d.ts.map +1 -0
  118. package/dist/types/tests/types/createElement.test.d.ts +2 -0
  119. package/dist/types/tests/types/createElement.test.d.ts.map +1 -0
  120. package/dist/types/tests/types/definition.test.d.ts +2 -0
  121. package/dist/types/tests/types/definition.test.d.ts.map +1 -0
  122. package/guide/zh_CN/advanced/binding_map_update.md +32 -0
  123. package/guide/zh_CN/advanced/build_args.md +28 -0
  124. package/guide/zh_CN/advanced/component_filter.md +70 -0
  125. package/guide/zh_CN/advanced/component_space.md +124 -0
  126. package/guide/zh_CN/advanced/custom_backend.md +53 -0
  127. package/guide/zh_CN/advanced/error_listener.md +32 -0
  128. package/guide/zh_CN/advanced/external_component.md +73 -0
  129. package/guide/zh_CN/advanced/template_engine.md +61 -0
  130. package/guide/zh_CN/appendix/backend_protocol.md +501 -0
  131. package/guide/zh_CN/appendix/list_diff_algorithm.md +406 -0
  132. package/guide/zh_CN/basic/beginning.md +94 -0
  133. package/guide/zh_CN/basic/component.md +156 -0
  134. package/guide/zh_CN/basic/event.md +169 -0
  135. package/guide/zh_CN/basic/lifetime.md +66 -0
  136. package/guide/zh_CN/basic/method.md +62 -0
  137. package/guide/zh_CN/basic/template.md +135 -0
  138. package/guide/zh_CN/data_management/advanced_update.md +170 -0
  139. package/guide/zh_CN/data_management/data_deep_copy.md +157 -0
  140. package/guide/zh_CN/data_management/data_observer.md +154 -0
  141. package/guide/zh_CN/data_management/property_early_init.md +31 -0
  142. package/guide/zh_CN/data_management/pure_data_pattern.md +21 -0
  143. package/guide/zh_CN/index.md +93 -0
  144. package/guide/zh_CN/interaction/behavior.md +52 -0
  145. package/guide/zh_CN/interaction/component_path.md +37 -0
  146. package/guide/zh_CN/interaction/generic.md +73 -0
  147. package/guide/zh_CN/interaction/placeholder.md +40 -0
  148. package/guide/zh_CN/interaction/relation.md +151 -0
  149. package/guide/zh_CN/interaction/slot.md +137 -0
  150. package/guide/zh_CN/interaction/template_import.md +94 -0
  151. package/guide/zh_CN/interaction/trait_behavior.md +117 -0
  152. package/guide/zh_CN/styling/external_class.md +46 -0
  153. package/guide/zh_CN/styling/style_isolation.md +54 -0
  154. package/guide/zh_CN/styling/virtual_host.md +52 -0
  155. package/guide/zh_CN/tree/element_iterator.md +54 -0
  156. package/guide/zh_CN/tree/mutation_observer.md +52 -0
  157. package/guide/zh_CN/tree/node_tree.md +142 -0
  158. package/guide/zh_CN/tree/node_tree_modification.md +78 -0
  159. package/guide/zh_CN/tree/selector.md +66 -0
  160. package/jest.config.js +6 -0
  161. package/jest.dts.config.js +9 -0
  162. package/jest.unit.config.js +14 -0
  163. package/package.json +28 -0
  164. package/src/backend/backend_protocol.ts +313 -0
  165. package/src/backend/composed_backend_protocol.ts +252 -0
  166. package/src/backend/domlike_backend_protocol.ts +370 -0
  167. package/src/backend/mode.ts +51 -0
  168. package/src/backend/suggested_backend_protocol.ts +83 -0
  169. package/src/behavior.ts +1655 -0
  170. package/src/bootstrap_dom_dev.js +22 -0
  171. package/src/class_list.ts +376 -0
  172. package/src/component.ts +1309 -0
  173. package/src/component_params.ts +461 -0
  174. package/src/component_space.ts +547 -0
  175. package/src/data_path.ts +225 -0
  176. package/src/data_proxy.ts +670 -0
  177. package/src/data_utils.ts +50 -0
  178. package/src/element.ts +1966 -0
  179. package/src/element_iterator.ts +158 -0
  180. package/src/event.ts +401 -0
  181. package/src/external_shadow_tree.ts +27 -0
  182. package/src/func_arr.ts +198 -0
  183. package/src/global_options.ts +242 -0
  184. package/src/index.ts +187 -0
  185. package/src/mutation_observer.ts +252 -0
  186. package/src/native_node.ts +74 -0
  187. package/src/node.ts +174 -0
  188. package/src/relation.ts +380 -0
  189. package/src/render.ts +25 -0
  190. package/src/selector.ts +218 -0
  191. package/src/shadow_root.ts +766 -0
  192. package/src/template_engine.ts +45 -0
  193. package/src/text_node.ts +149 -0
  194. package/src/tmpl/index.ts +199 -0
  195. package/src/tmpl/native_rendering.ts +175 -0
  196. package/src/tmpl/proc_gen_wrapper.ts +954 -0
  197. package/src/tmpl/proc_gen_wrapper_dom.ts +230 -0
  198. package/src/tmpl/range_list_diff.ts +443 -0
  199. package/src/trait_behaviors.ts +51 -0
  200. package/src/virtual_node.ts +51 -0
  201. package/tests/backend/domlike.test.ts +254 -0
  202. package/tests/base/env.ts +78 -0
  203. package/tests/base/match.ts +185 -0
  204. package/tests/core/backend.test.ts +144 -0
  205. package/tests/core/behavior.test.ts +546 -0
  206. package/tests/core/component_space.test.ts +212 -0
  207. package/tests/core/data_update.test.ts +461 -0
  208. package/tests/core/misc.test.ts +339 -0
  209. package/tests/core/placeholder.test.ts +180 -0
  210. package/tests/core/slot.test.ts +1495 -0
  211. package/tests/core/trait_behaviors.test.ts +153 -0
  212. package/tests/legacy/README.md +3 -0
  213. package/tests/legacy/behavior.test.js +293 -0
  214. package/tests/legacy/component.test.js +1247 -0
  215. package/tests/legacy/data_path.test.js +149 -0
  216. package/tests/legacy/data_proxy.test.js +759 -0
  217. package/tests/legacy/element_iterator.test.js +148 -0
  218. package/tests/legacy/event.test.js +849 -0
  219. package/tests/legacy/external.test.js +510 -0
  220. package/tests/legacy/extra_info.test.js +109 -0
  221. package/tests/legacy/generics.test.js +176 -0
  222. package/tests/legacy/mutation_observer.test.js +210 -0
  223. package/tests/legacy/relation.test.js +517 -0
  224. package/tests/legacy/selector.test.js +263 -0
  225. package/tests/legacy/slot.test.js +915 -0
  226. package/tests/legacy/virtual.test.js +394 -0
  227. package/tests/tmpl/binding_map.test.ts +208 -0
  228. package/tests/tmpl/event.test.ts +206 -0
  229. package/tests/tmpl/expression.test.ts +429 -0
  230. package/tests/tmpl/lvalue.test.ts +160 -0
  231. package/tests/tmpl/native_rendering.test.ts +155 -0
  232. package/tests/tmpl/structure.test.ts +998 -0
  233. package/tests/types/chaining.test.ts +614 -0
  234. package/tests/types/createElement.test.ts +82 -0
  235. package/tests/types/definition.test.ts +442 -0
  236. package/tsconfig.json +11 -0
  237. 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
+ }