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,954 @@
1
+ /* eslint-disable class-methods-use-this */
2
+
3
+ import { ProcGenGroupList } from '.'
4
+ import {
5
+ DataValue,
6
+ Element,
7
+ ShadowRoot,
8
+ VirtualNode,
9
+ TextNode,
10
+ Component,
11
+ GeneralComponent,
12
+ Node,
13
+ ShadowedEvent,
14
+ StyleSegmentIndex,
15
+ } from '..'
16
+ import {
17
+ DataPath,
18
+ } from '../data_path'
19
+ import { RangeListManager } from './range_list_diff'
20
+
21
+ export type UpdatePathTreeNode = true | { [key: string]: UpdatePathTreeNode } | UpdatePathTreeNode[]
22
+
23
+ export type UpdatePathTreeRoot = UpdatePathTreeNode | undefined
24
+
25
+ type TmplArgs = {
26
+ key?: number | string,
27
+ keyList?: RangeListManager,
28
+ scopeData?: unknown, // for wx:scope-data
29
+ dynEvListeners?: {
30
+ [name: string]: (ev: ShadowedEvent<unknown>) => boolean | undefined,
31
+ },
32
+ index?: number,
33
+ dynamicSlotNameMatched?: boolean,
34
+ slotProps?: Record<string, [DataValue, DataPath | null, boolean]>,
35
+ slotPropsUpdatePathTree?: Record<string, UpdatePathTreeRoot>,
36
+ }
37
+ export type TmplNode = Node & { _$wxTmplArgs?: TmplArgs }
38
+
39
+ export const getTmplArgs = (elem: Node): TmplArgs => {
40
+ const node = elem as TmplNode
41
+ // eslint-disable-next-line no-return-assign
42
+ return (node._$wxTmplArgs = node._$wxTmplArgs || {})
43
+ }
44
+
45
+ export const dataValueToString = (v: DataValue): string => {
46
+ if (v === null || v === undefined) {
47
+ return ''
48
+ }
49
+ return String(v)
50
+ }
51
+
52
+ const dashToCamelCase = (dash: string): string => {
53
+ const ret = dash.indexOf('-') <= 0
54
+ ? dash
55
+ : dash.replace(/-[a-z]/g, (s) => s[1]!.toUpperCase())
56
+ return ret
57
+ }
58
+
59
+ export type ProcGen = (
60
+ wrapper: ProcGenWrapper,
61
+ isCreation: boolean,
62
+ data: DataValue,
63
+ dataUpdatePathTree: UpdatePathTreeRoot,
64
+ ) => {
65
+ C: DefineChildren,
66
+ B?: { [field: string]: BindingMapGen[] },
67
+ }
68
+
69
+ export type ProcGenEnv = {
70
+ group: (name: string) => ProcGen,
71
+ list: ProcGenGroupList,
72
+ }
73
+
74
+ export type BindingMapGen = (
75
+ data: DataValue,
76
+ elementUpdated: (elem: Element) => void,
77
+ updateText: (node: TextNode, content: string) => void,
78
+ ) => void
79
+
80
+ export type DefineChildren = (
81
+ isCreation: boolean,
82
+ defineTextNode: DefineTextNode,
83
+ defineElement: DefineElement,
84
+ defineIfGroup: DefineIfGroup,
85
+ defineForLoop: DefineForLoop,
86
+ defineSlot: DefineSlot,
87
+ definePureVirtualNode: DefinePureVirtualNode,
88
+ dynamicSlotValues: { [name: string]: unknown } | undefined,
89
+ slotValueUpdatePathTrees: UpdatePathTreeNode | undefined,
90
+ ) => void
91
+
92
+ type DefineTextNode = (
93
+ text: string | undefined,
94
+ textInit?: (elem: TextNode) => boolean,
95
+ ) => void
96
+
97
+ type DefineElement = (
98
+ tag: string,
99
+ genericImpls: { [key: string]: string },
100
+ propertyInit: (elem: Element, isCreation: boolean) => void,
101
+ children: DefineChildren,
102
+ slot?: string,
103
+ dynamicSlotValueNames?: string[],
104
+ ) => void
105
+
106
+ type DefineIfGroup = (
107
+ branchKey: number | string,
108
+ branchFunc: DefineChildren,
109
+ ) => void
110
+
111
+ type DefineForLoop = (
112
+ list: DataValue[],
113
+ key: string | null,
114
+ oriListUpdatePathTree: UpdatePathTreeRoot,
115
+ lvaluePath: DataPath | null,
116
+ itemCallback: (
117
+ isCreation: boolean,
118
+ item: DataValue,
119
+ index: number | string,
120
+ itemUpdatePathTree: UpdatePathTreeRoot,
121
+ indexUpdatePathTree: UpdatePathTreeRoot,
122
+ itemLvaluePath: DataPath | null,
123
+ defineTextNode: DefineTextNode,
124
+ defineElement: DefineElement,
125
+ defineIfGroup: DefineIfGroup,
126
+ defineForLoop: DefineForLoop,
127
+ defineSlot: DefineSlot,
128
+ definePureVirtualNode: DefinePureVirtualNode,
129
+ ) => void,
130
+ ) => void
131
+
132
+ type DefineSlot = (
133
+ name: string | undefined,
134
+ slotValueInit?: (elem: Element) => void,
135
+ ) => void
136
+
137
+ type DefinePureVirtualNode = (
138
+ children: DefineChildren,
139
+ slot: string | undefined,
140
+ ) => void
141
+
142
+ export class ProcGenWrapper {
143
+ shadowRoot: ShadowRoot
144
+ procGen: ProcGen
145
+ disallowNativeNode: boolean
146
+ bindingMapDisabled = false
147
+
148
+ constructor(
149
+ shadowRoot: ShadowRoot,
150
+ procGen: ProcGen,
151
+ disallowNativeNode: boolean,
152
+ ) {
153
+ this.shadowRoot = shadowRoot
154
+ this.procGen = procGen
155
+ this.disallowNativeNode = disallowNativeNode
156
+ }
157
+
158
+ create(data: DataValue): { [field: string]: BindingMapGen[] } | undefined {
159
+ const { shadowRoot, procGen } = this
160
+ const children = procGen(this, true, data, undefined)
161
+ this.handleChildrenCreation(children.C, shadowRoot, undefined, undefined)
162
+ return children.B
163
+ }
164
+
165
+ update(data: DataValue, dataUpdatePathTree: UpdatePathTreeRoot): void {
166
+ const { shadowRoot, procGen } = this
167
+ const children = procGen(this, false, data, dataUpdatePathTree)
168
+ this.handleChildrenUpdate(children.C, shadowRoot, undefined, undefined)
169
+ }
170
+
171
+ bindingMapUpdate(
172
+ field: string,
173
+ data: DataValue,
174
+ bindingMapGenList: { [field: string]: BindingMapGen[] },
175
+ ): boolean {
176
+ if (this.bindingMapDisabled) return false
177
+ const updaters = bindingMapGenList[field]
178
+ if (!updaters) return false
179
+ let prevElement: Element | null = null
180
+ for (let i = 0; i < updaters.length; i += 1) {
181
+ const bindingMapGen = updaters[i]!
182
+ bindingMapGen(
183
+ data,
184
+ // eslint-disable-next-line no-loop-func
185
+ (elem: Element) => {
186
+ if (prevElement !== null && elem !== prevElement) {
187
+ if (prevElement instanceof Component) {
188
+ if (prevElement.hasPendingChanges()) {
189
+ const nodeDataProxy = Component.getDataProxy(prevElement)
190
+ nodeDataProxy.applyDataUpdates(true)
191
+ }
192
+ }
193
+ }
194
+ prevElement = elem
195
+ },
196
+ (elem: TextNode, v: string) => {
197
+ elem.textContent = v
198
+ },
199
+ )
200
+ }
201
+ const elem = prevElement as Element | null
202
+ if (elem !== null) {
203
+ if (elem instanceof Component) {
204
+ if (elem.hasPendingChanges()) {
205
+ const nodeDataProxy = Component.getDataProxy(elem)
206
+ nodeDataProxy.applyDataUpdates(true)
207
+ }
208
+ }
209
+ }
210
+ return true
211
+ }
212
+
213
+ handleChildrenCreation(
214
+ children: DefineChildren,
215
+ parentNode: Element,
216
+ slotElement: Element | undefined,
217
+ dynamicSlotName: string | undefined,
218
+ ): void {
219
+ children(
220
+ true,
221
+
222
+ // text node
223
+ (textContent: string | undefined, textInit?: (elem: TextNode) => void) => {
224
+ if (slotElement && dynamicSlotName !== '') {
225
+ const elem = this.createDynamicPlaceholder(slotElement)
226
+ parentNode.appendChild(elem)
227
+ return
228
+ }
229
+ const elem = this.shadowRoot.createTextNode(textContent)
230
+ elem.destroyBackendElementOnDetach()
231
+ if (slotElement) Element.setSlotElement(elem, slotElement)
232
+ if (textInit) textInit(elem)
233
+ parentNode.appendChild(elem)
234
+ },
235
+
236
+ // component or native node
237
+ (
238
+ tagName: string,
239
+ genericImpls: { [key: string]: string },
240
+ propertyInit: (elem: Element, isCreation: boolean) => void,
241
+ children: DefineChildren,
242
+ slot?: string,
243
+ dynamicSlotValueNames?: string[],
244
+ ) => {
245
+ if (slotElement && dynamicSlotName !== (slot || '')) {
246
+ const elem = this.createDynamicPlaceholder(slotElement)
247
+ parentNode.appendChild(elem)
248
+ return
249
+ }
250
+ const elem = this.createCommonElement(
251
+ tagName,
252
+ genericImpls,
253
+ propertyInit,
254
+ children,
255
+ dynamicSlotValueNames,
256
+ )
257
+ if (slotElement) {
258
+ Element.setSlotElement(elem, slotElement)
259
+ const tmplArgs = getTmplArgs(elem)
260
+ tmplArgs.dynamicSlotNameMatched = true
261
+ } else if (slot !== undefined) {
262
+ elem.slot = slot
263
+ }
264
+ parentNode.appendChild(elem)
265
+ },
266
+
267
+ // wx:if node or template-is node
268
+ (
269
+ branchKey: number | string,
270
+ branchFunc: DefineChildren,
271
+ ) => {
272
+ const elem = this.shadowRoot.createVirtualNode('wx:if')
273
+ elem.destroyBackendElementOnDetach()
274
+ Element.setInheritSlots(elem)
275
+ if (slotElement) Element.setSlotElement(elem, slotElement)
276
+ const tmplArgs = getTmplArgs(elem)
277
+ tmplArgs.key = branchKey
278
+ this.handleChildrenCreation(branchFunc, elem, slotElement, dynamicSlotName)
279
+ parentNode.appendChild(elem)
280
+ },
281
+
282
+ // wx:for node
283
+ (
284
+ list: DataValue[],
285
+ key: string | null,
286
+ oriListUpdatePathTree: UpdatePathTreeRoot,
287
+ lvaluePath: DataPath | null,
288
+ itemCallback: (
289
+ isCreation: boolean,
290
+ item: DataValue,
291
+ index: number | string,
292
+ itemUpdatePathTree: UpdatePathTreeRoot,
293
+ indexUpdatePathTree: UpdatePathTreeRoot,
294
+ itemLvaluePath: DataPath | null,
295
+ defineTextNode: DefineTextNode,
296
+ defineElement: DefineElement,
297
+ defineIfGroup: DefineIfGroup,
298
+ defineForLoop: DefineForLoop,
299
+ defineSlot: DefineSlot,
300
+ definePureVirtualNode: DefinePureVirtualNode,
301
+ ) => void,
302
+ ) => {
303
+ const shadowRoot = this.shadowRoot
304
+ const elem = shadowRoot.createVirtualNode('wx:for')
305
+ elem.destroyBackendElementOnDetach()
306
+ Element.setInheritSlots(elem)
307
+ if (slotElement) Element.setSlotElement(elem, slotElement)
308
+ const tmplArgs = getTmplArgs(elem)
309
+ tmplArgs.keyList = new RangeListManager(
310
+ key,
311
+ list,
312
+ elem,
313
+ (item: DataValue, index: number | string): VirtualNode => {
314
+ const childNode = shadowRoot.createVirtualNode('wx:for-item')
315
+ childNode.destroyBackendElementOnDetach()
316
+ Element.setInheritSlots(childNode)
317
+ if (slotElement) Element.setSlotElement(elem, slotElement)
318
+ this.handleChildrenCreation((
319
+ isCreation,
320
+ defineTextNode,
321
+ defineElement,
322
+ defineIfGroup,
323
+ defineForLoop,
324
+ defineSlot,
325
+ definePureVirtualNode,
326
+ ) => {
327
+ itemCallback(
328
+ true,
329
+ item,
330
+ index,
331
+ undefined,
332
+ undefined,
333
+ lvaluePath ? [...lvaluePath, index] : null,
334
+ defineTextNode,
335
+ defineElement,
336
+ defineIfGroup,
337
+ defineForLoop,
338
+ defineSlot,
339
+ definePureVirtualNode,
340
+ )
341
+ }, childNode, slotElement, dynamicSlotName)
342
+ return childNode
343
+ },
344
+ )
345
+ parentNode.appendChild(elem)
346
+ },
347
+
348
+ // slot node
349
+ (
350
+ slotName: string | undefined,
351
+ slotValueInit?: (elem: Element) => void,
352
+ ) => {
353
+ const elem = this.shadowRoot.createVirtualNode('slot')
354
+ elem.destroyBackendElementOnDetach()
355
+ Element.setSlotName(elem, dataValueToString(slotName))
356
+ if (slotElement) Element.setSlotElement(elem, slotElement)
357
+ if (slotValueInit) slotValueInit(elem)
358
+ parentNode.appendChild(elem)
359
+ },
360
+
361
+ // other virtual node
362
+ (
363
+ children: DefineChildren,
364
+ slot: string | undefined,
365
+ ) => {
366
+ if (slot !== undefined) {
367
+ if (slotElement) {
368
+ if (dynamicSlotName! === slot) {
369
+ const elem = this.shadowRoot.createVirtualNode('virtual')
370
+ elem.destroyBackendElementOnDetach()
371
+ Element.setSlotElement(elem, slotElement)
372
+ const tmplArgs = getTmplArgs(elem)
373
+ tmplArgs.dynamicSlotNameMatched = true
374
+ this.handleChildrenCreation(children, elem, undefined, undefined)
375
+ parentNode.appendChild(elem)
376
+ } else {
377
+ const elem = this.createDynamicPlaceholder(slotElement)
378
+ parentNode.appendChild(elem)
379
+ }
380
+ } else {
381
+ const elem = this.shadowRoot.createVirtualNode('virtual')
382
+ elem.destroyBackendElementOnDetach()
383
+ elem.slot = slot
384
+ this.handleChildrenCreation(children, elem, undefined, undefined)
385
+ parentNode.appendChild(elem)
386
+ }
387
+ } else {
388
+ const elem = this.shadowRoot.createVirtualNode('virtual')
389
+ elem.destroyBackendElementOnDetach()
390
+ Element.setInheritSlots(elem)
391
+ if (slotElement) Element.setSlotElement(elem, slotElement)
392
+ this.handleChildrenCreation(children, elem, slotElement, dynamicSlotName)
393
+ parentNode.appendChild(elem)
394
+ }
395
+ },
396
+ undefined,
397
+ undefined,
398
+ )
399
+ }
400
+
401
+ handleChildrenUpdate(
402
+ children: DefineChildren,
403
+ parentNode: Element,
404
+ slotElement: Element | undefined,
405
+ dynamicSlotName: string | undefined,
406
+ ): void {
407
+ let index = 0
408
+ const childNodes = slotElement
409
+ ? parentNode.childNodes.filter((node) => node._$nodeSlotElement === slotElement)
410
+ : parentNode.childNodes
411
+ children(
412
+ false,
413
+
414
+ // text node
415
+ (textContent: string | undefined) => {
416
+ const elem = childNodes[index] as TextNode
417
+ index += 1
418
+ if (slotElement) {
419
+ const tmplArgs = getTmplArgs(elem)
420
+ if (!tmplArgs.dynamicSlotNameMatched) {
421
+ return
422
+ }
423
+ }
424
+ if (textContent !== undefined) {
425
+ elem.textContent = textContent
426
+ }
427
+ },
428
+
429
+ // component or native node
430
+ (
431
+ tagName: string,
432
+ genericImpls: { [key: string]: string },
433
+ propertyInit: (elem: Element, isCreation: boolean) => void,
434
+ children: DefineChildren,
435
+ slot?: string,
436
+ dynamicSlotValueNames?: string[],
437
+ ) => {
438
+ const elem = childNodes[index] as Element
439
+ index += 1
440
+ if (slotElement) {
441
+ const tmplArgs = getTmplArgs(elem)
442
+ if (dynamicSlotName! === (slot || '')) {
443
+ if (!tmplArgs.dynamicSlotNameMatched) {
444
+ const newElem = this.createCommonElement(
445
+ tagName,
446
+ genericImpls,
447
+ propertyInit,
448
+ children,
449
+ dynamicSlotValueNames,
450
+ )
451
+ Element.setSlotElement(newElem, slotElement)
452
+ const newTmplArgs = getTmplArgs(newElem)
453
+ newTmplArgs.dynamicSlotNameMatched = true
454
+ parentNode.replaceChild(newElem, elem)
455
+ return
456
+ }
457
+ } else {
458
+ if (tmplArgs.dynamicSlotNameMatched) {
459
+ const newElem = this.createDynamicPlaceholder(slotElement)
460
+ parentNode.replaceChild(newElem, elem)
461
+ }
462
+ return
463
+ }
464
+ }
465
+ propertyInit(elem, false)
466
+ let dynSlot = false
467
+ if (elem instanceof Component) {
468
+ const sr = this.dynamicSlotUpdate(elem, dynamicSlotValueNames, children)
469
+ if (sr) dynSlot = true
470
+ if (elem.hasPendingChanges()) {
471
+ const nodeDataProxy = Component.getDataProxy(elem)
472
+ nodeDataProxy.applyDataUpdates(true)
473
+ }
474
+ sr?.applySlotUpdates()
475
+ }
476
+ if (!slotElement) {
477
+ if (slot !== undefined) elem.slot = slot
478
+ }
479
+ if (!dynSlot) {
480
+ this.handleChildrenUpdate(children, elem, undefined, undefined)
481
+ }
482
+ },
483
+
484
+ // wx:if node or template-is node
485
+ (
486
+ branchKey: number | string,
487
+ branchFunc: DefineChildren,
488
+ ) => {
489
+ const elem = childNodes[index] as Element
490
+ index += 1
491
+ const tmplArgs = getTmplArgs(elem)
492
+ if (tmplArgs.key === branchKey) {
493
+ this.handleChildrenUpdate(branchFunc, elem, slotElement, dynamicSlotName)
494
+ } else {
495
+ const newElem = this.shadowRoot.createVirtualNode('wx:if')
496
+ newElem.destroyBackendElementOnDetach()
497
+ Element.setInheritSlots(newElem)
498
+ if (slotElement) Element.setSlotElement(newElem, slotElement)
499
+ const tmplArgs = getTmplArgs(newElem)
500
+ tmplArgs.key = branchKey
501
+ this.handleChildrenCreation(branchFunc, newElem, slotElement, dynamicSlotName)
502
+ if (slotElement) parentNode.replaceChild(newElem, elem)
503
+ else parentNode.replaceChildAt(newElem, index - 1)
504
+ }
505
+ },
506
+
507
+ // wx:for node
508
+ (
509
+ list: DataValue[],
510
+ key: string | null,
511
+ oriListUpdatePathTree: UpdatePathTreeRoot,
512
+ lvaluePath: DataPath | null,
513
+ itemCallback: (
514
+ isCreation: boolean,
515
+ item: DataValue,
516
+ index: number | string,
517
+ itemUpdatePathTree: UpdatePathTreeRoot,
518
+ indexUpdatePathTree: UpdatePathTreeRoot,
519
+ itemLvaluePath: DataPath | null,
520
+ defineTextNode: DefineTextNode,
521
+ defineElement: DefineElement,
522
+ defineIfGroup: DefineIfGroup,
523
+ defineForLoop: DefineForLoop,
524
+ defineSlot: DefineSlot,
525
+ definePureVirtualNode: DefinePureVirtualNode,
526
+ ) => void,
527
+ ) => {
528
+ const elem = childNodes[index] as Element
529
+ index += 1
530
+ const tmplArgs = getTmplArgs(elem)
531
+ const keyListManager = tmplArgs.keyList!
532
+ keyListManager.diff(
533
+ list,
534
+ oriListUpdatePathTree,
535
+ elem,
536
+ (item: DataValue, index: number | string): VirtualNode => {
537
+ const childNode = this.shadowRoot.createVirtualNode('wx:for-item')
538
+ childNode.destroyBackendElementOnDetach()
539
+ Element.setInheritSlots(childNode)
540
+ if (slotElement) Element.setSlotElement(elem, slotElement)
541
+ this.handleChildrenCreation((
542
+ isCreation,
543
+ defineTextNode,
544
+ defineElement,
545
+ defineIfGroup,
546
+ defineForLoop,
547
+ defineSlot,
548
+ definePureVirtualNode,
549
+ ) => {
550
+ itemCallback(
551
+ true,
552
+ item,
553
+ index,
554
+ undefined,
555
+ undefined,
556
+ lvaluePath ? [...lvaluePath, index] : null,
557
+ defineTextNode,
558
+ defineElement,
559
+ defineIfGroup,
560
+ defineForLoop,
561
+ defineSlot,
562
+ definePureVirtualNode,
563
+ )
564
+ }, childNode, slotElement, dynamicSlotName)
565
+ return childNode
566
+ },
567
+ (
568
+ item: DataValue,
569
+ index: string | number,
570
+ updatePathTree: UpdatePathTreeRoot,
571
+ indexChanged: boolean,
572
+ childNode: Element,
573
+ ) => {
574
+ this.handleChildrenUpdate((
575
+ isCreation,
576
+ defineTextNode,
577
+ defineElement,
578
+ defineIfGroup,
579
+ defineForLoop,
580
+ defineSlot,
581
+ definePureVirtualNode,
582
+ ) => {
583
+ itemCallback(
584
+ false,
585
+ item,
586
+ index,
587
+ updatePathTree,
588
+ indexChanged ? true : undefined,
589
+ lvaluePath ? [...lvaluePath, index] : null,
590
+ defineTextNode,
591
+ defineElement,
592
+ defineIfGroup,
593
+ defineForLoop,
594
+ defineSlot,
595
+ definePureVirtualNode,
596
+ )
597
+ }, childNode, slotElement, dynamicSlotName)
598
+ },
599
+ )
600
+ },
601
+
602
+ // slot node
603
+ (
604
+ slotName: string | undefined,
605
+ slotValueInit?: (elem: Element) => void,
606
+ ) => {
607
+ const elem = childNodes[index] as Element
608
+ index += 1
609
+ if (slotName !== undefined) {
610
+ Element.setSlotName(elem, dataValueToString(slotName))
611
+ }
612
+ if (slotValueInit) slotValueInit(elem)
613
+ this.shadowRoot.applySlotValueUpdates(elem)
614
+ },
615
+
616
+ // other virtual node
617
+ (
618
+ children: DefineChildren,
619
+ slot: string | undefined,
620
+ ) => {
621
+ const elem = childNodes[index] as Element
622
+ index += 1
623
+ if (slot !== undefined) {
624
+ if (slotElement) {
625
+ const tmplArgs = getTmplArgs(elem)
626
+ if (dynamicSlotName! === slot) {
627
+ if (tmplArgs.dynamicSlotNameMatched) {
628
+ this.handleChildrenUpdate(children, elem, undefined, undefined)
629
+ } else {
630
+ const newElem = this.shadowRoot.createVirtualNode('virtual')
631
+ newElem.destroyBackendElementOnDetach()
632
+ Element.setSlotElement(newElem, slotElement)
633
+ const newTmplArgs = getTmplArgs(newElem)
634
+ newTmplArgs.dynamicSlotNameMatched = true
635
+ this.handleChildrenCreation(children, newElem, undefined, undefined)
636
+ parentNode.replaceChild(newElem, elem)
637
+ }
638
+ } else {
639
+ if (tmplArgs.dynamicSlotNameMatched) {
640
+ const newElem = this.createDynamicPlaceholder(slotElement)
641
+ parentNode.replaceChild(newElem, elem)
642
+ }
643
+ }
644
+ } else {
645
+ elem.slot = slot
646
+ this.handleChildrenUpdate(children, elem, undefined, undefined)
647
+ }
648
+ } else {
649
+ this.handleChildrenUpdate(children, elem, slotElement, dynamicSlotName)
650
+ }
651
+ },
652
+ undefined,
653
+ undefined,
654
+ )
655
+ }
656
+
657
+ dynamicSlotUpdate(
658
+ elem: GeneralComponent,
659
+ dynamicSlotValueNames: string[] | undefined,
660
+ children: DefineChildren,
661
+ ): ShadowRoot | null {
662
+ const sr = elem.getShadowRoot()
663
+ if (sr?.isDynamicSlots()) {
664
+ sr.setDynamicSlotHandler(
665
+ dynamicSlotValueNames || [],
666
+ (slot, slotName, slotValues) => {
667
+ this.handleChildrenCreation((
668
+ isCreation,
669
+ defineTextNode,
670
+ defineElement,
671
+ defineIfGroup,
672
+ defineForLoop,
673
+ defineSlot,
674
+ definePureVirtualNode,
675
+ ) => {
676
+ children(
677
+ true,
678
+ defineTextNode,
679
+ defineElement,
680
+ defineIfGroup,
681
+ defineForLoop,
682
+ defineSlot,
683
+ definePureVirtualNode,
684
+ slotValues,
685
+ undefined,
686
+ )
687
+ }, elem, slot, slotName)
688
+ },
689
+ (slot) => {
690
+ const childIndexes = []
691
+ for (let i = 0; i < elem.childNodes.length; i += 1) {
692
+ const child = elem.childNodes[i]!
693
+ if (sr.getContainingSlot(child) === slot) {
694
+ childIndexes.push(i)
695
+ }
696
+ }
697
+ for (let i = 0; i < childIndexes.length; i += 1) {
698
+ const childIndex = childIndexes[i]!
699
+ elem.removeChildAt(childIndex - i)
700
+ }
701
+ },
702
+ (slot, slotValues, slotValueUpdatePathTrees) => {
703
+ const slotName = slot._$slotName || ''
704
+ this.handleChildrenUpdate((
705
+ isCreation,
706
+ defineTextNode,
707
+ defineElement,
708
+ defineIfGroup,
709
+ defineForLoop,
710
+ defineSlot,
711
+ definePureVirtualNode,
712
+ ) => {
713
+ children(
714
+ false,
715
+ defineTextNode,
716
+ defineElement,
717
+ defineIfGroup,
718
+ defineForLoop,
719
+ defineSlot,
720
+ definePureVirtualNode,
721
+ slotValues,
722
+ slotValueUpdatePathTrees,
723
+ )
724
+ }, elem, slot, slotName)
725
+ },
726
+ )
727
+ return sr
728
+ }
729
+ return null
730
+ }
731
+
732
+ createDynamicPlaceholder(
733
+ slotElement: Element,
734
+ ): Element {
735
+ const elem = this.shadowRoot.createVirtualNode('virtual')
736
+ elem.destroyBackendElementOnDetach()
737
+ Element.setSlotElement(elem, slotElement)
738
+ const tmplArgs = getTmplArgs(elem)
739
+ tmplArgs.dynamicSlotNameMatched = false
740
+ return elem
741
+ }
742
+
743
+ createCommonElement(
744
+ tagName: string,
745
+ genericImpls: { [key: string]: string },
746
+ propertyInit: (elem: Element, isCreation: boolean) => void,
747
+ children: DefineChildren,
748
+ dynamicSlotValueNames: string[] | undefined,
749
+ ): Element {
750
+ const placeholding = this.shadowRoot.checkComponentPlaceholder(tagName)
751
+ let elem: Element
752
+ let dynSlot = false
753
+ if (this.disallowNativeNode || placeholding !== undefined) {
754
+ const initPropValues = (elem: GeneralComponent) => {
755
+ const sr = this.dynamicSlotUpdate(elem, dynamicSlotValueNames, children)
756
+ if (sr) dynSlot = true
757
+ propertyInit(elem, true)
758
+ if (elem.hasPendingChanges()) {
759
+ const nodeDataProxy = Component.getDataProxy(elem)
760
+ nodeDataProxy.applyDataUpdates(true)
761
+ }
762
+ sr?.applySlotUpdates()
763
+ }
764
+ let placeholderCb: (() => void) | undefined
765
+ if (placeholding) {
766
+ placeholderCb = () => {
767
+ const replacer = this.shadowRoot.createComponent(
768
+ tagName,
769
+ tagName,
770
+ genericImpls,
771
+ undefined,
772
+ initPropValues,
773
+ )
774
+ replacer.destroyBackendElementOnDetach()
775
+ const replacerShadowRoot = replacer.getShadowRoot()
776
+ const elemShadowRoot = (elem as GeneralComponent).getShadowRoot()
777
+ if (replacerShadowRoot?.isDynamicSlots()) {
778
+ if (!elemShadowRoot?.isDynamicSlots()) {
779
+ throw new Error('The "dynamicSlots" option of the component and its placeholder should be the same.')
780
+ }
781
+ elemShadowRoot.useDynamicSlotHandlerFrom(replacerShadowRoot)
782
+ elem.parentNode?.replaceChild(replacer, elem)
783
+ } else {
784
+ if (elemShadowRoot?.isDynamicSlots()) {
785
+ throw new Error('The "dynamicSlots" option of the component and its placeholder should be the same.')
786
+ }
787
+ elem.selfReplaceWith(replacer)
788
+ }
789
+ }
790
+ }
791
+ elem = this.shadowRoot.createComponent(
792
+ tagName,
793
+ tagName,
794
+ genericImpls,
795
+ placeholderCb,
796
+ initPropValues,
797
+ )
798
+ elem.destroyBackendElementOnDetach()
799
+ } else {
800
+ elem = this.shadowRoot.createComponentOrNativeNode(
801
+ tagName,
802
+ genericImpls,
803
+ (elem) => {
804
+ const sr = elem instanceof Component
805
+ ? this.dynamicSlotUpdate(elem, dynamicSlotValueNames, children)
806
+ : null
807
+ if (sr) dynSlot = true
808
+ propertyInit(elem, true)
809
+ if (elem instanceof Component) {
810
+ if (elem.hasPendingChanges()) {
811
+ const nodeDataProxy = Component.getDataProxy(elem)
812
+ nodeDataProxy.applyDataUpdates(true)
813
+ }
814
+ sr?.applySlotUpdates()
815
+ }
816
+ },
817
+ )
818
+ elem.destroyBackendElementOnDetach()
819
+ }
820
+ if (dynSlot) {
821
+ this.bindingMapDisabled = true // IDEA better binding map disable detection
822
+ } else {
823
+ this.handleChildrenCreation(children, elem, undefined, undefined)
824
+ }
825
+ return elem
826
+ }
827
+
828
+ // set slot
829
+ // (not used any more, leaving for compatibilities)
830
+ s(elem: Element, v: string) {
831
+ elem.slot = v
832
+ }
833
+
834
+ // set slot value
835
+ l(elem: Element, name: string, value: unknown) {
836
+ this.shadowRoot.replaceSlotValue(elem, name, value)
837
+ }
838
+
839
+ // set id
840
+ i(elem: Element, v: string) {
841
+ elem.id = v
842
+ }
843
+
844
+ // set class or external classes named `class`
845
+ c(elem: Element, v: string) {
846
+ if (elem instanceof Component) {
847
+ // "class" itself can also be an external class
848
+ const hasExternalClass = (elem as GeneralComponent).hasExternalClass('class')
849
+ if (hasExternalClass) {
850
+ (elem as GeneralComponent).setExternalClass('class', dataValueToString(v))
851
+ }
852
+ elem.class = dataValueToString(v)
853
+ } else {
854
+ elem.class = dataValueToString(v)
855
+ }
856
+ }
857
+
858
+ // set style or property named `style`
859
+ y(elem: Element, v: string) {
860
+ elem.setNodeStyle(dataValueToString(v), StyleSegmentIndex.MAIN)
861
+ }
862
+
863
+ // set dataset
864
+ d(elem: Element, name: string, v: unknown) {
865
+ let dataset: { [name: string]: unknown }
866
+ if (elem.dataset) dataset = elem.dataset
867
+ else dataset = elem.dataset = {}
868
+ dataset[name] = v
869
+ }
870
+
871
+ // set mark
872
+ m(elem: Element, name: string, v: unknown) {
873
+ elem.setMark(name, v)
874
+ }
875
+
876
+ // set event handler
877
+ v(
878
+ elem: Element,
879
+ evName: string,
880
+ v: string,
881
+ final: boolean,
882
+ mutated: boolean,
883
+ capture: boolean,
884
+ isDynamic: boolean,
885
+ ) {
886
+ const handlerName = dataValueToString(v)
887
+ const listener = (ev: ShadowedEvent<unknown>) => {
888
+ const host = elem.ownerShadowRoot!.getHostNode()
889
+ let ret: boolean | undefined
890
+ const methodCaller = host.getMethodCaller() as { [key: string]: unknown }
891
+ const f = host._$methodMap[handlerName]
892
+ if (typeof f === 'function') {
893
+ ret = (f as (ev: ShadowedEvent<unknown>) => boolean | undefined).call(methodCaller, ev)
894
+ }
895
+ return ret
896
+ }
897
+ const evOptions = {
898
+ final,
899
+ mutated,
900
+ capture,
901
+ }
902
+ if (isDynamic) {
903
+ const tmplArgs = getTmplArgs(elem)
904
+ if (!tmplArgs.dynEvListeners) tmplArgs.dynEvListeners = {}
905
+ const dynEvListeners = tmplArgs.dynEvListeners
906
+ if (dynEvListeners[evName]) {
907
+ elem.removeListener(evName, dynEvListeners[evName]!, evOptions)
908
+ }
909
+ dynEvListeners[evName] = listener
910
+ }
911
+ if (handlerName) elem.addListener(evName, listener, evOptions)
912
+ }
913
+
914
+ // set scope-data
915
+ sd(elem: Element, scopeData: unknown) {
916
+ const tmplArgs = getTmplArgs(elem)
917
+ tmplArgs.scopeData = scopeData
918
+ }
919
+
920
+ // update a property or external class of a component, or an attribute of a native node
921
+ r(elem: Element, name: string, v: unknown, lvaluePath?: DataPath) {
922
+ if (elem instanceof Component) {
923
+ const nodeDataProxy = Component.getDataProxy(elem)
924
+ const camelName = dashToCamelCase(name)
925
+ if (nodeDataProxy.replaceProperty(camelName, v)) {
926
+ if (lvaluePath) {
927
+ nodeDataProxy.setModelBindingListener(camelName, (value) => {
928
+ const host = elem.ownerShadowRoot!.getHostNode()
929
+ const nodeDataProxy = Component.getDataProxy(host)
930
+ nodeDataProxy.replaceDataOnPath(lvaluePath, value)
931
+ nodeDataProxy.applyDataUpdates(false)
932
+ })
933
+ }
934
+ } else if (elem.hasExternalClass(name)) {
935
+ elem.setExternalClass(name, dataValueToString(v))
936
+ } else {
937
+ // compatibilities for legacy event binding syntax
938
+ if (camelName.startsWith('bind')) {
939
+ ProcGenWrapper.prototype.v(elem, camelName.slice('bind'.length), dataValueToString(v), false, false, false, true)
940
+ } else if (camelName.startsWith('captureBind')) {
941
+ ProcGenWrapper.prototype.v(elem, camelName.slice('captureBind'.length), dataValueToString(v), false, false, true, true)
942
+ } else if (camelName.startsWith('catch')) {
943
+ ProcGenWrapper.prototype.v(elem, camelName.slice('catch'.length), dataValueToString(v), true, false, false, true)
944
+ } else if (camelName.startsWith('captureCatch')) {
945
+ ProcGenWrapper.prototype.v(elem, camelName.slice('captureCatch'.length), dataValueToString(v), true, false, true, true)
946
+ } else if (camelName.startsWith('on')) {
947
+ ProcGenWrapper.prototype.v(elem, camelName.slice('on'.length), dataValueToString(v), false, false, false, true)
948
+ }
949
+ }
950
+ } else {
951
+ elem.updateAttribute(name, v)
952
+ }
953
+ }
954
+ }