glass-easel 0.2.0 → 0.3.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/.eslintignore +4 -0
- package/dist/glass_easel.all.js +2 -2
- package/dist/glass_easel.all.js.map +1 -1
- package/dist/glass_easel.d.ts +2546 -0
- package/dist/glass_easel.domlike.global.js +2 -2
- package/dist/glass_easel.domlike.global.js.map +1 -1
- package/guide/zh_CN/appendix/backend_protocol.md +164 -74
- package/jest.unit.config.js +7 -4
- package/package.json +7 -5
- package/rollup.config.ts +101 -0
- package/src/backend/backend_protocol.ts +26 -345
- package/src/backend/composed_backend_protocol.ts +10 -264
- package/src/backend/current_window_backend_context.ts +478 -0
- package/src/backend/domlike_backend_protocol.ts +9 -498
- package/src/backend/empty_backend.ts +265 -0
- package/src/backend/empty_composed_backend.ts +245 -0
- package/src/backend/index.ts +18 -0
- package/src/backend/suggested_backend_protocol.ts +62 -11
- package/src/behavior.ts +131 -442
- package/src/class_list.ts +328 -222
- package/src/component.ts +349 -184
- package/src/component_params.ts +54 -25
- package/src/component_space.ts +36 -15
- package/src/data_path.ts +22 -34
- package/src/data_proxy.ts +334 -27
- package/src/devtool.ts +89 -0
- package/src/element.ts +667 -285
- package/src/element_iterator.ts +9 -4
- package/src/event.ts +39 -20
- package/src/external_shadow_tree.ts +2 -2
- package/src/func_arr.ts +55 -101
- package/src/global_options.ts +18 -42
- package/src/index.ts +72 -73
- package/src/mutation_observer.ts +10 -7
- package/src/native_node.ts +79 -35
- package/src/node.ts +23 -30
- package/src/relation.ts +101 -12
- package/src/render.ts +5 -3
- package/src/selector.ts +9 -7
- package/src/shadow_root.ts +96 -240
- package/src/template_engine.ts +10 -7
- package/src/text_node.ts +43 -19
- package/src/tmpl/index.ts +38 -30
- package/src/tmpl/native_rendering.ts +14 -21
- package/src/tmpl/proc_gen_wrapper.ts +189 -151
- package/src/tmpl/proc_gen_wrapper_dom.ts +10 -8
- package/src/tmpl/range_list_diff.ts +30 -9
- package/src/trait_behaviors.ts +1 -1
- package/src/type_symbol.ts +36 -0
- package/src/virtual_node.ts +26 -13
- package/src/warning.ts +119 -0
- package/tests/base/composed_backend.ts +143 -142
- package/tests/base/env.ts +76 -3
- package/tests/base/match.ts +24 -22
- package/tests/base/shadow_backend.ts +917 -0
- package/tests/core/backend.test.ts +53 -1
- package/tests/core/behavior.test.ts +1 -1
- package/tests/core/data_update.test.ts +135 -0
- package/tests/core/misc.test.ts +91 -21
- package/tests/core/placeholder.test.ts +66 -25
- package/tests/core/slot.test.ts +161 -23
- package/tests/legacy/component.test.js +152 -78
- package/tests/legacy/data_path.test.js +19 -19
- package/tests/legacy/data_proxy.test.js +14 -7
- package/tests/legacy/external.test.js +8 -8
- package/tests/legacy/mutation_observer.test.js +7 -5
- package/tests/legacy/slot.test.js +2 -3
- package/tests/legacy/virtual.test.js +258 -25
- package/tests/tmpl/binding_map.test.ts +201 -195
- package/tests/tmpl/event.test.ts +138 -23
- package/tests/tmpl/expression.test.ts +15 -15
- package/tests/tmpl/lvalue.test.ts +101 -0
- package/tests/tmpl/structure.test.ts +486 -43
- package/tests/types/chaining.test.ts +27 -30
- package/tests/types/createElement.test.ts +5 -4
- package/tests/types/definition.test.ts +11 -14
- package/tsconfig.json +1 -3
- package/dist/glass_easel.all.d.ts +0 -1
- package/dist/glass_easel.domlike.global.d.ts +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/types/src/backend/backend_protocol.d.ts +0 -141
- package/dist/types/src/backend/backend_protocol.d.ts.map +0 -1
- package/dist/types/src/backend/composed_backend_protocol.d.ts +0 -102
- package/dist/types/src/backend/composed_backend_protocol.d.ts.map +0 -1
- package/dist/types/src/backend/domlike_backend_protocol.d.ts +0 -100
- package/dist/types/src/backend/domlike_backend_protocol.d.ts.map +0 -1
- package/dist/types/src/backend/mode.d.ts +0 -65
- package/dist/types/src/backend/mode.d.ts.map +0 -1
- package/dist/types/src/backend/suggested_backend_protocol.d.ts +0 -30
- package/dist/types/src/backend/suggested_backend_protocol.d.ts.map +0 -1
- package/dist/types/src/behavior.d.ts +0 -434
- package/dist/types/src/behavior.d.ts.map +0 -1
- package/dist/types/src/class_list.d.ts +0 -83
- package/dist/types/src/class_list.d.ts.map +0 -1
- package/dist/types/src/component.d.ts +0 -325
- package/dist/types/src/component.d.ts.map +0 -1
- package/dist/types/src/component_params.d.ts +0 -236
- package/dist/types/src/component_params.d.ts.map +0 -1
- package/dist/types/src/component_space.d.ts +0 -211
- package/dist/types/src/component_space.d.ts.map +0 -1
- package/dist/types/src/data_path.d.ts +0 -5
- package/dist/types/src/data_path.d.ts.map +0 -1
- package/dist/types/src/data_proxy.d.ts +0 -107
- package/dist/types/src/data_proxy.d.ts.map +0 -1
- package/dist/types/src/data_utils.d.ts +0 -3
- package/dist/types/src/data_utils.d.ts.map +0 -1
- package/dist/types/src/element.d.ts +0 -365
- package/dist/types/src/element.d.ts.map +0 -1
- package/dist/types/src/element_iterator.d.ts +0 -43
- package/dist/types/src/element_iterator.d.ts.map +0 -1
- package/dist/types/src/event.d.ts +0 -105
- package/dist/types/src/event.d.ts.map +0 -1
- package/dist/types/src/external_shadow_tree.d.ts +0 -20
- package/dist/types/src/external_shadow_tree.d.ts.map +0 -1
- package/dist/types/src/func_arr.d.ts +0 -39
- package/dist/types/src/func_arr.d.ts.map +0 -1
- package/dist/types/src/global_options.d.ts +0 -120
- package/dist/types/src/global_options.d.ts.map +0 -1
- package/dist/types/src/index.d.ts +0 -43
- package/dist/types/src/index.d.ts.map +0 -1
- package/dist/types/src/mutation_observer.d.ts +0 -79
- package/dist/types/src/mutation_observer.d.ts.map +0 -1
- package/dist/types/src/native_node.d.ts +0 -11
- package/dist/types/src/native_node.d.ts.map +0 -1
- package/dist/types/src/node.d.ts +0 -48
- package/dist/types/src/node.d.ts.map +0 -1
- package/dist/types/src/relation.d.ts +0 -46
- package/dist/types/src/relation.d.ts.map +0 -1
- package/dist/types/src/render.d.ts +0 -3
- package/dist/types/src/render.d.ts.map +0 -1
- package/dist/types/src/selector.d.ts +0 -32
- package/dist/types/src/selector.d.ts.map +0 -1
- package/dist/types/src/shadow_root.d.ts +0 -174
- package/dist/types/src/shadow_root.d.ts.map +0 -1
- package/dist/types/src/template_engine.d.ts +0 -56
- package/dist/types/src/template_engine.d.ts.map +0 -1
- package/dist/types/src/text_node.d.ts +0 -44
- package/dist/types/src/text_node.d.ts.map +0 -1
- package/dist/types/src/tmpl/index.d.ts +0 -19
- package/dist/types/src/tmpl/index.d.ts.map +0 -1
- package/dist/types/src/tmpl/native_rendering.d.ts +0 -45
- package/dist/types/src/tmpl/native_rendering.d.ts.map +0 -1
- package/dist/types/src/tmpl/proc_gen_wrapper.d.ts +0 -89
- package/dist/types/src/tmpl/proc_gen_wrapper.d.ts.map +0 -1
- package/dist/types/src/tmpl/proc_gen_wrapper_dom.d.ts +0 -50
- package/dist/types/src/tmpl/proc_gen_wrapper_dom.d.ts.map +0 -1
- package/dist/types/src/tmpl/range_list_diff.d.ts +0 -19
- package/dist/types/src/tmpl/range_list_diff.d.ts.map +0 -1
- package/dist/types/src/trait_behaviors.d.ts +0 -38
- package/dist/types/src/trait_behaviors.d.ts.map +0 -1
- package/dist/types/src/virtual_node.d.ts +0 -10
- package/dist/types/src/virtual_node.d.ts.map +0 -1
- package/dist/types/tests/backend/domlike.test.d.ts +0 -2
- package/dist/types/tests/backend/domlike.test.d.ts.map +0 -1
- package/dist/types/tests/base/composed_backend.d.ts +0 -123
- package/dist/types/tests/base/composed_backend.d.ts.map +0 -1
- package/dist/types/tests/base/env.d.ts +0 -30
- package/dist/types/tests/base/env.d.ts.map +0 -1
- package/dist/types/tests/base/match.d.ts +0 -9
- package/dist/types/tests/base/match.d.ts.map +0 -1
- package/dist/types/tests/core/backend.test.d.ts +0 -2
- package/dist/types/tests/core/backend.test.d.ts.map +0 -1
- package/dist/types/tests/core/behavior.test.d.ts +0 -2
- package/dist/types/tests/core/behavior.test.d.ts.map +0 -1
- package/dist/types/tests/core/component_space.test.d.ts +0 -2
- package/dist/types/tests/core/component_space.test.d.ts.map +0 -1
- package/dist/types/tests/core/data_update.test.d.ts +0 -2
- package/dist/types/tests/core/data_update.test.d.ts.map +0 -1
- package/dist/types/tests/core/misc.test.d.ts +0 -2
- package/dist/types/tests/core/misc.test.d.ts.map +0 -1
- package/dist/types/tests/core/placeholder.test.d.ts +0 -2
- package/dist/types/tests/core/placeholder.test.d.ts.map +0 -1
- package/dist/types/tests/core/slot.test.d.ts +0 -2
- package/dist/types/tests/core/slot.test.d.ts.map +0 -1
- package/dist/types/tests/core/trait_behaviors.test.d.ts +0 -2
- package/dist/types/tests/core/trait_behaviors.test.d.ts.map +0 -1
- package/dist/types/tests/tmpl/binding_map.test.d.ts +0 -2
- package/dist/types/tests/tmpl/binding_map.test.d.ts.map +0 -1
- package/dist/types/tests/tmpl/event.test.d.ts +0 -2
- package/dist/types/tests/tmpl/event.test.d.ts.map +0 -1
- package/dist/types/tests/tmpl/expression.test.d.ts +0 -2
- package/dist/types/tests/tmpl/expression.test.d.ts.map +0 -1
- package/dist/types/tests/tmpl/lvalue.test.d.ts +0 -2
- package/dist/types/tests/tmpl/lvalue.test.d.ts.map +0 -1
- package/dist/types/tests/tmpl/native_rendering.test.d.ts +0 -2
- package/dist/types/tests/tmpl/native_rendering.test.d.ts.map +0 -1
- package/dist/types/tests/tmpl/structure.test.d.ts +0 -2
- package/dist/types/tests/tmpl/structure.test.d.ts.map +0 -1
- package/dist/types/tests/types/chaining.test.d.ts +0 -2
- package/dist/types/tests/types/chaining.test.d.ts.map +0 -1
- package/dist/types/tests/types/createElement.test.d.ts +0 -2
- package/dist/types/tests/types/createElement.test.d.ts.map +0 -1
- package/dist/types/tests/types/definition.test.d.ts +0 -2
- package/dist/types/tests/types/definition.test.d.ts.map +0 -1
- package/webpack.config.js +0 -275
- /package/src/backend/{mode.ts → shared.ts} +0 -0
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
/* eslint-disable class-methods-use-this */
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
} from '
|
|
17
|
-
import { DataPath } from '../data_path'
|
|
18
|
-
import { SlotMode } from '../shadow_root'
|
|
3
|
+
import { Component, type GeneralComponent } from '../component'
|
|
4
|
+
import { type DataPath } from '../data_path'
|
|
5
|
+
import { type DataValue } from '../data_proxy'
|
|
6
|
+
import { Element, StyleSegmentIndex } from '../element'
|
|
7
|
+
import { type ShadowedEvent } from '../event'
|
|
8
|
+
import { ENV } from '../global_options'
|
|
9
|
+
import { type NativeNode } from '../native_node'
|
|
10
|
+
import { type Node } from '../node'
|
|
11
|
+
import { SlotMode, type ShadowRoot } from '../shadow_root'
|
|
12
|
+
import { type TextNode } from '../text_node'
|
|
13
|
+
import { type ProcGenGroupList } from '../tmpl'
|
|
14
|
+
import { isComponent, isNativeNode } from '../type_symbol'
|
|
15
|
+
import { type VirtualNode } from '../virtual_node'
|
|
16
|
+
import { dispatchError } from '../warning'
|
|
19
17
|
import { RangeListManager } from './range_list_diff'
|
|
20
18
|
|
|
21
19
|
export type UpdatePathTreeNode = true | { [key: string]: UpdatePathTreeNode } | UpdatePathTreeNode[]
|
|
@@ -133,14 +131,18 @@ type DefineForLoop = (
|
|
|
133
131
|
) => void,
|
|
134
132
|
) => void
|
|
135
133
|
|
|
136
|
-
type DefineSlot = (
|
|
134
|
+
type DefineSlot = (
|
|
135
|
+
name: string | undefined,
|
|
136
|
+
slotValueInit?: (elem: Element) => void,
|
|
137
|
+
slot?: string,
|
|
138
|
+
) => void
|
|
137
139
|
|
|
138
140
|
type DefinePureVirtualNode = (children: DefineChildren, slot: string | undefined) => void
|
|
139
141
|
|
|
140
142
|
export class ProcGenWrapper {
|
|
141
143
|
shadowRoot: ShadowRoot
|
|
142
144
|
procGen: ProcGen
|
|
143
|
-
|
|
145
|
+
fallbackListenerOnNativeNode: boolean
|
|
144
146
|
bindingMapDisabled = false
|
|
145
147
|
eventObjectFilter: (x: ShadowedEvent<unknown>) => ShadowedEvent<unknown> = emptyFilter
|
|
146
148
|
changePropFilter = emptyFilter
|
|
@@ -149,12 +151,12 @@ export class ProcGenWrapper {
|
|
|
149
151
|
constructor(
|
|
150
152
|
shadowRoot: ShadowRoot,
|
|
151
153
|
procGen: ProcGen,
|
|
152
|
-
|
|
154
|
+
fallbackListenerOnNativeNode: boolean,
|
|
153
155
|
eventObjectFilter?: (x: ShadowedEvent<unknown>) => ShadowedEvent<unknown>,
|
|
154
156
|
) {
|
|
155
157
|
this.shadowRoot = shadowRoot
|
|
156
158
|
this.procGen = procGen
|
|
157
|
-
this.
|
|
159
|
+
this.fallbackListenerOnNativeNode = fallbackListenerOnNativeNode
|
|
158
160
|
if (eventObjectFilter) {
|
|
159
161
|
this.eventObjectFilter = eventObjectFilter
|
|
160
162
|
}
|
|
@@ -189,7 +191,7 @@ export class ProcGenWrapper {
|
|
|
189
191
|
// eslint-disable-next-line no-loop-func
|
|
190
192
|
(elem: Element) => {
|
|
191
193
|
if (prevElement !== null && elem !== prevElement) {
|
|
192
|
-
if (prevElement
|
|
194
|
+
if (isComponent(prevElement)) {
|
|
193
195
|
if (prevElement.hasPendingChanges()) {
|
|
194
196
|
const nodeDataProxy = Component.getDataProxy(prevElement)
|
|
195
197
|
nodeDataProxy.applyDataUpdates(true)
|
|
@@ -205,7 +207,7 @@ export class ProcGenWrapper {
|
|
|
205
207
|
}
|
|
206
208
|
const elem = prevElement as Element | null
|
|
207
209
|
if (elem !== null) {
|
|
208
|
-
if (elem
|
|
210
|
+
if (isComponent(elem)) {
|
|
209
211
|
if (elem.hasPendingChanges()) {
|
|
210
212
|
const nodeDataProxy = Component.getDataProxy(elem)
|
|
211
213
|
nodeDataProxy.applyDataUpdates(true)
|
|
@@ -312,6 +314,7 @@ export class ProcGenWrapper {
|
|
|
312
314
|
key,
|
|
313
315
|
list,
|
|
314
316
|
elem,
|
|
317
|
+
shadowRoot,
|
|
315
318
|
(item: DataValue, index: number | string): VirtualNode => {
|
|
316
319
|
const childNode = shadowRoot.createVirtualNode('wx:for-item')
|
|
317
320
|
childNode.destroyBackendElementOnDetach()
|
|
@@ -353,11 +356,15 @@ export class ProcGenWrapper {
|
|
|
353
356
|
},
|
|
354
357
|
|
|
355
358
|
// slot node
|
|
356
|
-
(slotName: string | undefined, slotValueInit?: (elem: Element) => void) => {
|
|
359
|
+
(slotName: string | undefined, slotValueInit?: (elem: Element) => void, slot?: string) => {
|
|
357
360
|
const elem = this.shadowRoot.createVirtualNode('slot')
|
|
358
361
|
elem.destroyBackendElementOnDetach()
|
|
359
362
|
Element.setSlotName(elem, dataValueToString(slotName))
|
|
360
|
-
if (slotElement)
|
|
363
|
+
if (slotElement) {
|
|
364
|
+
Element.setSlotElement(elem, slotElement)
|
|
365
|
+
} else if (slot !== undefined) {
|
|
366
|
+
elem.slot = slot
|
|
367
|
+
}
|
|
361
368
|
if (slotValueInit) slotValueInit(elem)
|
|
362
369
|
childNodes.push(elem)
|
|
363
370
|
},
|
|
@@ -476,7 +483,7 @@ export class ProcGenWrapper {
|
|
|
476
483
|
}
|
|
477
484
|
propertyInit(elem, false)
|
|
478
485
|
let dynSlot = false
|
|
479
|
-
if (elem
|
|
486
|
+
if (isComponent(elem)) {
|
|
480
487
|
const sr = this.dynamicSlotUpdate(elem, dynamicSlotValueNames, children)
|
|
481
488
|
if (sr) dynSlot = true
|
|
482
489
|
if (elem.hasPendingChanges()) {
|
|
@@ -619,12 +626,15 @@ export class ProcGenWrapper {
|
|
|
619
626
|
},
|
|
620
627
|
|
|
621
628
|
// slot node
|
|
622
|
-
(slotName: string | undefined, slotValueInit?: (elem: Element) => void) => {
|
|
629
|
+
(slotName: string | undefined, slotValueInit?: (elem: Element) => void, slot?: string) => {
|
|
623
630
|
const elem = childNodes[index] as Element
|
|
624
631
|
index += 1
|
|
625
632
|
if (slotName !== undefined) {
|
|
626
633
|
Element.setSlotName(elem, dataValueToString(slotName))
|
|
627
634
|
}
|
|
635
|
+
if (!slotElement) {
|
|
636
|
+
if (slot !== undefined) elem.slot = slot
|
|
637
|
+
}
|
|
628
638
|
if (slotValueInit) slotValueInit(elem)
|
|
629
639
|
this.shadowRoot.applySlotValueUpdates(elem)
|
|
630
640
|
},
|
|
@@ -782,17 +792,14 @@ export class ProcGenWrapper {
|
|
|
782
792
|
children: DefineChildren,
|
|
783
793
|
dynamicSlotValueNames: string[] | undefined,
|
|
784
794
|
): Element {
|
|
785
|
-
const placeholding = this.shadowRoot.checkComponentPlaceholder(tagName)
|
|
786
|
-
let elem: Element
|
|
787
795
|
let dynSlot = false
|
|
788
796
|
const initPropValues = (elem: GeneralComponent | NativeNode) => {
|
|
789
|
-
const sr =
|
|
790
|
-
elem
|
|
791
|
-
|
|
792
|
-
: null
|
|
797
|
+
const sr = isComponent(elem)
|
|
798
|
+
? this.dynamicSlotUpdate(elem, dynamicSlotValueNames, children)
|
|
799
|
+
: null
|
|
793
800
|
if (sr) dynSlot = true
|
|
794
801
|
propertyInit(elem, true)
|
|
795
|
-
if (elem
|
|
802
|
+
if (isComponent(elem)) {
|
|
796
803
|
if (elem.hasPendingChanges()) {
|
|
797
804
|
const nodeDataProxy = Component.getDataProxy(elem)
|
|
798
805
|
nodeDataProxy.applyDataUpdates(true)
|
|
@@ -800,55 +807,41 @@ export class ProcGenWrapper {
|
|
|
800
807
|
sr?.applySlotUpdates()
|
|
801
808
|
}
|
|
802
809
|
}
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
if (placeholding) {
|
|
806
|
-
placeholderCb = () => {
|
|
807
|
-
const replacer = this.shadowRoot.createComponent(
|
|
808
|
-
tagName,
|
|
809
|
-
tagName,
|
|
810
|
-
genericImpls,
|
|
811
|
-
undefined,
|
|
812
|
-
initPropValues,
|
|
813
|
-
)
|
|
814
|
-
replacer.destroyBackendElementOnDetach()
|
|
815
|
-
const replacerShadowRoot = (replacer as GeneralComponent).getShadowRoot()
|
|
816
|
-
const elemShadowRoot = elem instanceof Component ? elem.getShadowRoot() : null
|
|
817
|
-
const isElemDynamicSlots = elemShadowRoot?.getSlotMode() === SlotMode.Dynamic
|
|
818
|
-
const isReplacerDynamicSlots = replacerShadowRoot?.getSlotMode() === SlotMode.Dynamic
|
|
819
|
-
if (isReplacerDynamicSlots) {
|
|
820
|
-
if (!isElemDynamicSlots) {
|
|
821
|
-
throw new Error(
|
|
822
|
-
'The "dynamicSlots" option of the component and its placeholder should be the same.',
|
|
823
|
-
)
|
|
824
|
-
}
|
|
825
|
-
elem.parentNode?.replaceChild(replacer, elem)
|
|
826
|
-
} else {
|
|
827
|
-
if (isElemDynamicSlots) {
|
|
828
|
-
throw new Error(
|
|
829
|
-
'The "dynamicSlots" option of the component and its placeholder should be the same.',
|
|
830
|
-
)
|
|
831
|
-
}
|
|
832
|
-
elem.selfReplaceWith(replacer)
|
|
833
|
-
}
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
elem = this.shadowRoot.createComponent(
|
|
810
|
+
const placeholderCallback = () => {
|
|
811
|
+
const replacer = this.shadowRoot.createComponent(
|
|
837
812
|
tagName,
|
|
838
813
|
tagName,
|
|
839
814
|
genericImpls,
|
|
840
|
-
|
|
841
|
-
initPropValues,
|
|
842
|
-
)
|
|
843
|
-
elem.destroyBackendElementOnDetach()
|
|
844
|
-
} else {
|
|
845
|
-
elem = this.shadowRoot.createComponentOrNativeNode(
|
|
846
|
-
placeholding ?? tagName,
|
|
847
|
-
genericImpls,
|
|
815
|
+
undefined,
|
|
848
816
|
initPropValues,
|
|
849
817
|
)
|
|
850
|
-
|
|
818
|
+
replacer.destroyBackendElementOnDetach()
|
|
819
|
+
const replacerShadowRoot = (replacer as GeneralComponent).getShadowRoot()
|
|
820
|
+
const elemShadowRoot = isComponent(elem) ? elem.getShadowRoot() : null
|
|
821
|
+
const isElemDynamicSlots = elemShadowRoot?.getSlotMode() === SlotMode.Dynamic
|
|
822
|
+
const isReplacerDynamicSlots = replacerShadowRoot?.getSlotMode() === SlotMode.Dynamic
|
|
823
|
+
if (isReplacerDynamicSlots !== isElemDynamicSlots) {
|
|
824
|
+
dispatchError(
|
|
825
|
+
new Error(
|
|
826
|
+
`The "dynamicSlots" option of component <${replacer.is}> and its placeholder <${elem.is}> should be the same.`,
|
|
827
|
+
),
|
|
828
|
+
'[render]',
|
|
829
|
+
isComponent(replacer) ? replacer : replacer.is,
|
|
830
|
+
)
|
|
831
|
+
} else if (isReplacerDynamicSlots) {
|
|
832
|
+
elem.parentNode?.replaceChild(replacer, elem)
|
|
833
|
+
} else {
|
|
834
|
+
elem.selfReplaceWith(replacer)
|
|
835
|
+
}
|
|
851
836
|
}
|
|
837
|
+
const elem = this.shadowRoot.createComponent(
|
|
838
|
+
tagName,
|
|
839
|
+
tagName,
|
|
840
|
+
genericImpls,
|
|
841
|
+
placeholderCallback,
|
|
842
|
+
initPropValues,
|
|
843
|
+
)
|
|
844
|
+
elem.destroyBackendElementOnDetach()
|
|
852
845
|
if (dynSlot) {
|
|
853
846
|
this.bindingMapDisabled = true // IDEA better binding map disable detection
|
|
854
847
|
} else {
|
|
@@ -874,22 +867,26 @@ export class ProcGenWrapper {
|
|
|
874
867
|
}
|
|
875
868
|
|
|
876
869
|
// set class or external classes named `class`
|
|
877
|
-
c(elem: Element, v: string) {
|
|
878
|
-
if (elem
|
|
870
|
+
c(elem: Element, v: string | string[]) {
|
|
871
|
+
if (isComponent(elem)) {
|
|
879
872
|
// "class" itself can also be an external class
|
|
880
|
-
const hasExternalClass =
|
|
873
|
+
const hasExternalClass = elem.hasExternalClass('class')
|
|
881
874
|
if (hasExternalClass) {
|
|
882
|
-
|
|
875
|
+
elem.setExternalClass('class', v)
|
|
883
876
|
}
|
|
884
|
-
elem.class = dataValueToString(v)
|
|
885
|
-
} else {
|
|
886
|
-
elem.class = dataValueToString(v)
|
|
887
877
|
}
|
|
878
|
+
elem.setNodeClass(v)
|
|
888
879
|
}
|
|
889
880
|
|
|
890
881
|
// set style or property named `style`
|
|
891
882
|
y(elem: Element, v: string) {
|
|
892
|
-
elem.
|
|
883
|
+
if (isComponent(elem) && Component.hasProperty(elem, 'style')) {
|
|
884
|
+
const nodeDataProxy = Component.getDataProxy(elem)
|
|
885
|
+
const camelName = dashToCamelCase('style')
|
|
886
|
+
nodeDataProxy.replaceProperty(camelName, v)
|
|
887
|
+
} else {
|
|
888
|
+
elem.setNodeStyle(dataValueToString(v), StyleSegmentIndex.MAIN)
|
|
889
|
+
}
|
|
893
890
|
}
|
|
894
891
|
|
|
895
892
|
// set dataset
|
|
@@ -911,6 +908,7 @@ export class ProcGenWrapper {
|
|
|
911
908
|
mutated: boolean,
|
|
912
909
|
capture: boolean,
|
|
913
910
|
isDynamic: boolean,
|
|
911
|
+
_generalLvaluePath?: DataPath | null,
|
|
914
912
|
) {
|
|
915
913
|
const handler = typeof v === 'function' ? this.eventListenerFilter(v) : dataValueToString(v)
|
|
916
914
|
const listener = (ev: ShadowedEvent<unknown>) => {
|
|
@@ -927,6 +925,11 @@ export class ProcGenWrapper {
|
|
|
927
925
|
}
|
|
928
926
|
return ret
|
|
929
927
|
}
|
|
928
|
+
if (ENV.DEV) {
|
|
929
|
+
Object.defineProperty(listener, 'name', {
|
|
930
|
+
value: typeof handler === 'string' ? handler : handler.name,
|
|
931
|
+
})
|
|
932
|
+
}
|
|
930
933
|
const evOptions = {
|
|
931
934
|
final,
|
|
932
935
|
mutated,
|
|
@@ -945,18 +948,89 @@ export class ProcGenWrapper {
|
|
|
945
948
|
}
|
|
946
949
|
|
|
947
950
|
// update a property or external class of a component, or an attribute of a native node
|
|
948
|
-
r
|
|
949
|
-
|
|
951
|
+
r = (
|
|
952
|
+
elem: Element,
|
|
953
|
+
name: string,
|
|
954
|
+
v: unknown,
|
|
955
|
+
modelLvaluePath?: DataPath | null,
|
|
956
|
+
generalLvaluePath?: DataPath | null,
|
|
957
|
+
) => {
|
|
958
|
+
const checkFallbackEventListener = (camelName: string) => {
|
|
959
|
+
if (camelName.startsWith('bind')) {
|
|
960
|
+
this.v(
|
|
961
|
+
elem,
|
|
962
|
+
camelName.slice('bind'.length),
|
|
963
|
+
dataValueToString(v),
|
|
964
|
+
false,
|
|
965
|
+
false,
|
|
966
|
+
false,
|
|
967
|
+
true,
|
|
968
|
+
generalLvaluePath,
|
|
969
|
+
)
|
|
970
|
+
} else if (camelName.startsWith('captureBind')) {
|
|
971
|
+
this.v(
|
|
972
|
+
elem,
|
|
973
|
+
camelName.slice('captureBind'.length),
|
|
974
|
+
dataValueToString(v),
|
|
975
|
+
false,
|
|
976
|
+
false,
|
|
977
|
+
true,
|
|
978
|
+
true,
|
|
979
|
+
generalLvaluePath,
|
|
980
|
+
)
|
|
981
|
+
} else if (camelName.startsWith('catch')) {
|
|
982
|
+
this.v(
|
|
983
|
+
elem,
|
|
984
|
+
camelName.slice('catch'.length),
|
|
985
|
+
dataValueToString(v),
|
|
986
|
+
true,
|
|
987
|
+
false,
|
|
988
|
+
false,
|
|
989
|
+
true,
|
|
990
|
+
generalLvaluePath,
|
|
991
|
+
)
|
|
992
|
+
} else if (camelName.startsWith('captureCatch')) {
|
|
993
|
+
this.v(
|
|
994
|
+
elem,
|
|
995
|
+
camelName.slice('captureCatch'.length),
|
|
996
|
+
dataValueToString(v),
|
|
997
|
+
true,
|
|
998
|
+
false,
|
|
999
|
+
true,
|
|
1000
|
+
true,
|
|
1001
|
+
generalLvaluePath,
|
|
1002
|
+
)
|
|
1003
|
+
} else if (camelName.startsWith('on')) {
|
|
1004
|
+
this.v(
|
|
1005
|
+
elem,
|
|
1006
|
+
camelName.slice('on'.length),
|
|
1007
|
+
dataValueToString(v),
|
|
1008
|
+
false,
|
|
1009
|
+
false,
|
|
1010
|
+
false,
|
|
1011
|
+
true,
|
|
1012
|
+
generalLvaluePath,
|
|
1013
|
+
)
|
|
1014
|
+
} else {
|
|
1015
|
+
return false
|
|
1016
|
+
}
|
|
1017
|
+
return true
|
|
1018
|
+
}
|
|
1019
|
+
if (isComponent(elem)) {
|
|
950
1020
|
const nodeDataProxy = Component.getDataProxy(elem)
|
|
951
1021
|
const camelName = dashToCamelCase(name)
|
|
952
1022
|
if (nodeDataProxy.replaceProperty(camelName, v)) {
|
|
953
|
-
if (
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
nodeDataProxy.
|
|
958
|
-
|
|
959
|
-
|
|
1023
|
+
if (modelLvaluePath !== undefined) {
|
|
1024
|
+
if (modelLvaluePath === null) {
|
|
1025
|
+
nodeDataProxy.setModelBindingListener(camelName, () => {})
|
|
1026
|
+
} else {
|
|
1027
|
+
nodeDataProxy.setModelBindingListener(camelName, (value) => {
|
|
1028
|
+
const host = elem.ownerShadowRoot!.getHostNode()
|
|
1029
|
+
const nodeDataProxy = Component.getDataProxy(host)
|
|
1030
|
+
nodeDataProxy.replaceDataOnPath(modelLvaluePath, value)
|
|
1031
|
+
nodeDataProxy.applyDataUpdates(false)
|
|
1032
|
+
})
|
|
1033
|
+
}
|
|
960
1034
|
}
|
|
961
1035
|
const tmplArgs = getTmplArgs(elem)
|
|
962
1036
|
if (tmplArgs.changeProp?.[name]) {
|
|
@@ -969,68 +1043,26 @@ export class ProcGenWrapper {
|
|
|
969
1043
|
}
|
|
970
1044
|
}
|
|
971
1045
|
} else if (elem.hasExternalClass(name)) {
|
|
972
|
-
elem.setExternalClass(name,
|
|
1046
|
+
elem.setExternalClass(name, v as string)
|
|
973
1047
|
} else {
|
|
974
1048
|
// compatibilities for legacy event binding syntax
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
true,
|
|
984
|
-
)
|
|
985
|
-
} else if (camelName.startsWith('captureBind')) {
|
|
986
|
-
this.v(
|
|
987
|
-
elem,
|
|
988
|
-
camelName.slice('captureBind'.length),
|
|
989
|
-
dataValueToString(v),
|
|
990
|
-
false,
|
|
991
|
-
false,
|
|
992
|
-
true,
|
|
993
|
-
true,
|
|
994
|
-
)
|
|
995
|
-
} else if (camelName.startsWith('catch')) {
|
|
996
|
-
this.v(
|
|
997
|
-
elem,
|
|
998
|
-
camelName.slice('catch'.length),
|
|
999
|
-
dataValueToString(v),
|
|
1000
|
-
true,
|
|
1001
|
-
false,
|
|
1002
|
-
false,
|
|
1003
|
-
true,
|
|
1004
|
-
)
|
|
1005
|
-
} else if (camelName.startsWith('captureCatch')) {
|
|
1006
|
-
this.v(
|
|
1007
|
-
elem,
|
|
1008
|
-
camelName.slice('captureCatch'.length),
|
|
1009
|
-
dataValueToString(v),
|
|
1010
|
-
true,
|
|
1011
|
-
false,
|
|
1012
|
-
true,
|
|
1013
|
-
true,
|
|
1014
|
-
)
|
|
1015
|
-
} else if (camelName.startsWith('on')) {
|
|
1016
|
-
this.v(
|
|
1017
|
-
elem,
|
|
1018
|
-
camelName.slice('on'.length),
|
|
1019
|
-
dataValueToString(v),
|
|
1020
|
-
false,
|
|
1021
|
-
false,
|
|
1022
|
-
false,
|
|
1023
|
-
true,
|
|
1024
|
-
)
|
|
1049
|
+
checkFallbackEventListener(camelName)
|
|
1050
|
+
}
|
|
1051
|
+
} else if (isNativeNode(elem)) {
|
|
1052
|
+
if (this.fallbackListenerOnNativeNode) {
|
|
1053
|
+
// compatibilities for legacy event binding syntax
|
|
1054
|
+
const camelName = dashToCamelCase(name)
|
|
1055
|
+
if (!checkFallbackEventListener(camelName)) {
|
|
1056
|
+
elem.updateAttribute(name, v)
|
|
1025
1057
|
}
|
|
1058
|
+
} else {
|
|
1059
|
+
elem.updateAttribute(name, v)
|
|
1026
1060
|
}
|
|
1027
|
-
|
|
1028
|
-
elem.updateAttribute(name, v)
|
|
1029
|
-
if (lvaluePath) {
|
|
1061
|
+
if (modelLvaluePath) {
|
|
1030
1062
|
elem.setModelBindingListener(name, (value) => {
|
|
1031
1063
|
const host = elem.ownerShadowRoot!.getHostNode()
|
|
1032
1064
|
const nodeDataProxy = Component.getDataProxy(host)
|
|
1033
|
-
nodeDataProxy.replaceDataOnPath(
|
|
1065
|
+
nodeDataProxy.replaceDataOnPath(modelLvaluePath, value)
|
|
1034
1066
|
nodeDataProxy.applyDataUpdates(false)
|
|
1035
1067
|
})
|
|
1036
1068
|
}
|
|
@@ -1039,7 +1071,7 @@ export class ProcGenWrapper {
|
|
|
1039
1071
|
|
|
1040
1072
|
// set a worklet directive value
|
|
1041
1073
|
wl(elem: Element, name: string, value: unknown) {
|
|
1042
|
-
if (elem
|
|
1074
|
+
if (isComponent(elem)) {
|
|
1043
1075
|
elem.triggerWorkletChangeLifetime(name, value)
|
|
1044
1076
|
} else {
|
|
1045
1077
|
// TODO warn unused worklet
|
|
@@ -1047,8 +1079,8 @@ export class ProcGenWrapper {
|
|
|
1047
1079
|
}
|
|
1048
1080
|
|
|
1049
1081
|
// add a change property binding
|
|
1050
|
-
p(elem: Element, name: string, v: ChangePropListener) {
|
|
1051
|
-
if (elem
|
|
1082
|
+
p(elem: Element, name: string, v: ChangePropListener, _generalLvaluePath?: DataPath | null) {
|
|
1083
|
+
if (isComponent(elem)) {
|
|
1052
1084
|
if (Component.hasProperty(elem, name)) {
|
|
1053
1085
|
const tmplArgs = getTmplArgs(elem)
|
|
1054
1086
|
if (!tmplArgs.changeProp) {
|
|
@@ -1068,3 +1100,9 @@ export class ProcGenWrapper {
|
|
|
1068
1100
|
this.eventListenerFilter = eventListenerFilter
|
|
1069
1101
|
}
|
|
1070
1102
|
}
|
|
1103
|
+
|
|
1104
|
+
export const enum GeneralLvaluePathPrefix {
|
|
1105
|
+
Data = 0,
|
|
1106
|
+
Script = 1, // `abs_path` followed
|
|
1107
|
+
InlineScript = 2, // `abs_path` and `mod_name` followed
|
|
1108
|
+
}
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
/* eslint-disable class-methods-use-this */
|
|
2
2
|
/* global document */
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
import { DataPath } from '../data_path'
|
|
6
|
-
import {
|
|
4
|
+
import { type GeneralBackendElement } from '../backend'
|
|
5
|
+
import { type DataPath } from '../data_path'
|
|
6
|
+
import { type DataValue } from '../data_proxy'
|
|
7
|
+
import { type ShadowedEvent } from '../event'
|
|
8
|
+
import { type GlassEaselTemplateDOMInstance } from './native_rendering'
|
|
7
9
|
import {
|
|
8
|
-
ProcGen,
|
|
9
|
-
BindingMapGen,
|
|
10
|
-
UpdatePathTreeRoot,
|
|
11
10
|
dataValueToString,
|
|
12
|
-
|
|
11
|
+
type BindingMapGen,
|
|
12
|
+
type ProcGen,
|
|
13
|
+
type ProcGenWrapper,
|
|
14
|
+
type UpdatePathTreeRoot,
|
|
13
15
|
} from './proc_gen_wrapper'
|
|
14
|
-
import type
|
|
16
|
+
import { type RangeListManager } from './range_list_diff'
|
|
15
17
|
|
|
16
18
|
type TmplArgs = {
|
|
17
19
|
key?: number | string
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { type DataValue } from '../data_proxy'
|
|
2
|
+
import { type Element } from '../element'
|
|
3
|
+
import { type ShadowRoot } from '../shadow_root'
|
|
4
|
+
import { type VirtualNode } from '../virtual_node'
|
|
5
|
+
import { triggerWarning } from '../warning'
|
|
6
|
+
import { type UpdatePathTreeNode, type UpdatePathTreeRoot } from './proc_gen_wrapper'
|
|
5
7
|
|
|
6
8
|
export class RangeListManager {
|
|
7
9
|
keyName: string | null
|
|
@@ -10,13 +12,18 @@ export class RangeListManager {
|
|
|
10
12
|
sharedKeyMap!: { [key: string]: number[] } | undefined
|
|
11
13
|
items!: DataValue[]
|
|
12
14
|
indexes!: (string | number)[] | null
|
|
15
|
+
ownerShadowRoot: ShadowRoot
|
|
16
|
+
elem: Element
|
|
13
17
|
|
|
14
18
|
constructor(
|
|
15
19
|
keyName: string | null,
|
|
16
20
|
dataList: DataValue,
|
|
17
21
|
elem: Element,
|
|
22
|
+
shadowRoot: ShadowRoot,
|
|
18
23
|
newListItem: (item: DataValue, index: number | string) => VirtualNode,
|
|
19
24
|
) {
|
|
25
|
+
this.ownerShadowRoot = shadowRoot
|
|
26
|
+
this.elem = elem
|
|
20
27
|
this.keyName = keyName
|
|
21
28
|
this.updateKeys(dataList)
|
|
22
29
|
const items = this.items
|
|
@@ -50,6 +57,8 @@ export class RangeListManager {
|
|
|
50
57
|
} else if (typeof dataList === 'string') {
|
|
51
58
|
triggerWarning(
|
|
52
59
|
'Use string as for-list is generally for testing. Each character is treated as an item.',
|
|
60
|
+
this.ownerShadowRoot.getHostNode(),
|
|
61
|
+
this.elem,
|
|
53
62
|
)
|
|
54
63
|
items = new Array<string>(dataList.length)
|
|
55
64
|
indexes = null
|
|
@@ -59,6 +68,8 @@ export class RangeListManager {
|
|
|
59
68
|
} else if (typeof dataList === 'number') {
|
|
60
69
|
triggerWarning(
|
|
61
70
|
'Use number as for-list is generally for testing. The number is used as the repeated times of the item.',
|
|
71
|
+
this.ownerShadowRoot.getHostNode(),
|
|
72
|
+
this.elem,
|
|
62
73
|
)
|
|
63
74
|
items = new Array<string>(dataList)
|
|
64
75
|
indexes = null
|
|
@@ -66,7 +77,13 @@ export class RangeListManager {
|
|
|
66
77
|
items[i] = i
|
|
67
78
|
}
|
|
68
79
|
} else {
|
|
69
|
-
triggerWarning(
|
|
80
|
+
triggerWarning(
|
|
81
|
+
`The for-list data is neither Array nor Object, got type "${
|
|
82
|
+
dataList === null ? 'null' : typeof dataList
|
|
83
|
+
}".`,
|
|
84
|
+
this.ownerShadowRoot.getHostNode(),
|
|
85
|
+
this.elem,
|
|
86
|
+
)
|
|
70
87
|
items = []
|
|
71
88
|
indexes = null
|
|
72
89
|
}
|
|
@@ -100,7 +117,11 @@ export class RangeListManager {
|
|
|
100
117
|
// convert shared keys to unique keys
|
|
101
118
|
if (sharedKeyMap) {
|
|
102
119
|
const keys = Object.keys(sharedKeyMap)
|
|
103
|
-
triggerWarning(
|
|
120
|
+
triggerWarning(
|
|
121
|
+
`Some keys are not unique while list updates: "${keys.join('", "')}".`,
|
|
122
|
+
this.ownerShadowRoot.getHostNode(),
|
|
123
|
+
this.elem,
|
|
124
|
+
)
|
|
104
125
|
for (let i = 0; i < keys.length; i += 1) {
|
|
105
126
|
const key = keys[i]!
|
|
106
127
|
const items = sharedKeyMap[key]!
|
|
@@ -327,12 +348,12 @@ export class RangeListManager {
|
|
|
327
348
|
// decide what operation to be used with each item
|
|
328
349
|
const enum OpKind {
|
|
329
350
|
Stable = 0,
|
|
330
|
-
ForwardMove,
|
|
331
|
-
BackwardMove,
|
|
351
|
+
ForwardMove, // move towards the array end (index increasing direction)
|
|
352
|
+
BackwardMove, // move towards the array start (index decreasing direction)
|
|
332
353
|
}
|
|
333
354
|
const oldListOp = new Array(oldRawKeys.length) as (OpKind | undefined)[]
|
|
334
355
|
const changedItems = new Array(newRawKeys.length) as (VirtualNode | undefined)[]
|
|
335
|
-
let prevLcsOldPos =
|
|
356
|
+
let prevLcsOldPos = -1
|
|
336
357
|
for (let i = 0; i < oldPosList.length; i += 1) {
|
|
337
358
|
const oldPos = oldPosList[i]!
|
|
338
359
|
if (i === lcsArr[curLcsArrIndex]) {
|
package/src/trait_behaviors.ts
CHANGED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type GeneralComponent } from './component'
|
|
2
|
+
import { type Element } from './element'
|
|
3
|
+
import { type NativeNode } from './native_node'
|
|
4
|
+
import { type ShadowRoot } from './shadow_root'
|
|
5
|
+
import { type TextNode } from './text_node'
|
|
6
|
+
import { type VirtualNode } from './virtual_node'
|
|
7
|
+
|
|
8
|
+
export const TEXT_NODE_SYMBOL = Symbol('TextNode')
|
|
9
|
+
|
|
10
|
+
export const ELEMENT_SYMBOL = Symbol('Element')
|
|
11
|
+
|
|
12
|
+
export const NATIVE_NODE_SYMBOL = Symbol('NativeNode')
|
|
13
|
+
|
|
14
|
+
export const VIRTUAL_NODE_SYMBOL = Symbol('VirtualNode')
|
|
15
|
+
|
|
16
|
+
export const SHADOW_ROOT_SYMBOL = Symbol('ShadowRootSymbol')
|
|
17
|
+
|
|
18
|
+
export const COMPONENT_SYMBOL = Symbol('Component')
|
|
19
|
+
|
|
20
|
+
export const isTextNode = (e: any): e is TextNode =>
|
|
21
|
+
!!e && (e as { [TEXT_NODE_SYMBOL]: boolean })[TEXT_NODE_SYMBOL]
|
|
22
|
+
|
|
23
|
+
export const isElement = (e: any): e is Element =>
|
|
24
|
+
!!e && (e as { [ELEMENT_SYMBOL]: boolean })[ELEMENT_SYMBOL]
|
|
25
|
+
|
|
26
|
+
export const isNativeNode = (e: any): e is NativeNode =>
|
|
27
|
+
!!e && (e as { [NATIVE_NODE_SYMBOL]: boolean })[NATIVE_NODE_SYMBOL]
|
|
28
|
+
|
|
29
|
+
export const isVirtualNode = (e: any): e is VirtualNode =>
|
|
30
|
+
!!e && (e as { [VIRTUAL_NODE_SYMBOL]: boolean })[VIRTUAL_NODE_SYMBOL]
|
|
31
|
+
|
|
32
|
+
export const isShadowRoot = (e: any): e is ShadowRoot =>
|
|
33
|
+
!!e && (e as { [SHADOW_ROOT_SYMBOL]: boolean })[SHADOW_ROOT_SYMBOL]
|
|
34
|
+
|
|
35
|
+
export const isComponent = (e: any): e is GeneralComponent =>
|
|
36
|
+
!!e && (e as { [COMPONENT_SYMBOL]: boolean })[COMPONENT_SYMBOL]
|