@wsxjs/wsx-core 0.0.20 → 0.0.21
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/dist/chunk-AR3DIDLV.mjs +906 -0
- package/dist/index.js +671 -111
- package/dist/index.mjs +137 -17
- package/dist/jsx-runtime.js +541 -99
- package/dist/jsx-runtime.mjs +1 -1
- package/dist/jsx.js +541 -99
- package/dist/jsx.mjs +1 -1
- package/package.json +2 -2
- package/src/base-component.ts +15 -0
- package/src/dom-cache-manager.ts +135 -0
- package/src/jsx-factory.ts +73 -451
- package/src/light-component.ts +3 -2
- package/src/reactive-decorator.ts +9 -0
- package/src/render-context.ts +40 -0
- package/src/utils/cache-key.ts +114 -0
- package/src/utils/dom-utils.ts +119 -0
- package/src/utils/element-creation.ts +140 -0
- package/src/utils/element-marking.ts +80 -0
- package/src/utils/element-update.ts +377 -0
- package/src/utils/props-utils.ts +307 -0
- package/src/web-component.ts +2 -1
- package/dist/chunk-7FXISNME.mjs +0 -462
- package/dist/tsconfig.tsbuildinfo +0 -1
package/dist/jsx.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wsxjs/wsx-core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.21",
|
|
4
4
|
"description": "Core WSXJS - Web Components with JSX syntax",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"custom-elements"
|
|
49
49
|
],
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@wsxjs/wsx-logger": "0.0.
|
|
51
|
+
"@wsxjs/wsx-logger": "0.0.21"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"tsup": "^8.0.0",
|
package/src/base-component.ts
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import { reactive as createReactive, createState, reactiveWithDebug } from "./utils/reactive";
|
|
12
|
+
import { DOMCacheManager } from "./dom-cache-manager";
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Type for reactive state storage
|
|
@@ -60,6 +61,12 @@ export abstract class BaseComponent extends HTMLElement {
|
|
|
60
61
|
*/
|
|
61
62
|
protected _autoStyles?: string;
|
|
62
63
|
|
|
64
|
+
/**
|
|
65
|
+
* DOM Cache Manager for fine-grained updates (RFC 0037)
|
|
66
|
+
* @internal
|
|
67
|
+
*/
|
|
68
|
+
protected _domCache = new DOMCacheManager();
|
|
69
|
+
|
|
63
70
|
/**
|
|
64
71
|
* 当前捕获的焦点状态(用于在 render 时使用捕获的值)
|
|
65
72
|
* @internal - 由 rerender() 方法管理
|
|
@@ -138,6 +145,14 @@ export abstract class BaseComponent extends HTMLElement {
|
|
|
138
145
|
*/
|
|
139
146
|
protected onRendered?(): void;
|
|
140
147
|
|
|
148
|
+
/**
|
|
149
|
+
* Gets the DOMCacheManager instance.
|
|
150
|
+
* @internal
|
|
151
|
+
*/
|
|
152
|
+
public getDomCache(): DOMCacheManager {
|
|
153
|
+
return this._domCache;
|
|
154
|
+
}
|
|
155
|
+
|
|
141
156
|
/**
|
|
142
157
|
* 处理 blur 事件,在用户停止输入时执行待处理的重渲染
|
|
143
158
|
* @internal
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { createLogger } from "./utils/logger";
|
|
2
|
+
|
|
3
|
+
const logger = createLogger("DOMCacheManager");
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Parent container information for duplicate key detection
|
|
7
|
+
*/
|
|
8
|
+
interface ParentInfo {
|
|
9
|
+
parentTag: string;
|
|
10
|
+
parentClass: string;
|
|
11
|
+
element: Element;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* DOMCacheManager
|
|
16
|
+
*
|
|
17
|
+
* Manages DOM element caching for fine-grained updates (RFC 0037).
|
|
18
|
+
* Stores elements by unique keys derived from component ID + position/key.
|
|
19
|
+
*/
|
|
20
|
+
export class DOMCacheManager {
|
|
21
|
+
// Map<CacheKey, DOMElement>
|
|
22
|
+
private cache = new Map<string, Element>();
|
|
23
|
+
|
|
24
|
+
// Map<DOMElement, Metadata>
|
|
25
|
+
// Stores metadata (props, children) for cached elements to support diffing
|
|
26
|
+
private metadata = new WeakMap<Element, Record<string, unknown>>();
|
|
27
|
+
|
|
28
|
+
// Track key-parent relationships to detect duplicate keys in all environments
|
|
29
|
+
// Map<CacheKey, ParentInfo>
|
|
30
|
+
private keyParentMap = new Map<string, ParentInfo>();
|
|
31
|
+
|
|
32
|
+
// Flag to enable duplicate key warnings (enabled by default, critical for correctness)
|
|
33
|
+
private warnDuplicateKeys = true;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Retrieves an element from the cache.
|
|
37
|
+
* @param key The unique cache key.
|
|
38
|
+
*/
|
|
39
|
+
get(key: string): Element | undefined {
|
|
40
|
+
return this.cache.get(key);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Stores an element in the cache.
|
|
45
|
+
* @param key The unique cache key.
|
|
46
|
+
* @param element The DOM element to cache.
|
|
47
|
+
*/
|
|
48
|
+
set(key: string, element: Element): void {
|
|
49
|
+
// Always check for duplicate keys (critical for correctness)
|
|
50
|
+
if (this.warnDuplicateKeys) {
|
|
51
|
+
this.checkDuplicateKey(key, element);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
this.cache.set(key, element);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Checks if a cache key is being reused in a different parent container.
|
|
59
|
+
* Runs in all environments to help developers catch key conflicts early.
|
|
60
|
+
* This is critical for correctness and helps prevent subtle bugs.
|
|
61
|
+
*/
|
|
62
|
+
private checkDuplicateKey(key: string, element: Element): void {
|
|
63
|
+
const existing = this.keyParentMap.get(key);
|
|
64
|
+
const currentParent = element.parentElement;
|
|
65
|
+
|
|
66
|
+
if (existing && currentParent) {
|
|
67
|
+
const currentParentInfo = this.getParentInfo(currentParent);
|
|
68
|
+
const existingParentInfo = `${existing.parentTag}${existing.parentClass ? "." + existing.parentClass : ""}`;
|
|
69
|
+
|
|
70
|
+
// Check if the element is being used in a different parent container
|
|
71
|
+
if (currentParentInfo !== existingParentInfo) {
|
|
72
|
+
logger.warn(
|
|
73
|
+
`Duplicate key "${key}" detected in different parent containers!\n` +
|
|
74
|
+
` Previous parent: ${existingParentInfo}\n` +
|
|
75
|
+
` Current parent: ${currentParentInfo}\n` +
|
|
76
|
+
`\n` +
|
|
77
|
+
`This may cause elements to appear in wrong containers or be moved unexpectedly.\n` +
|
|
78
|
+
`\n` +
|
|
79
|
+
`Solution: Use unique key prefixes for different locations:\n` +
|
|
80
|
+
` Example: <wsx-link key="nav-0"> vs <wsx-link key="overflow-0">\n` +
|
|
81
|
+
`\n` +
|
|
82
|
+
`See https://wsxjs.dev/docs/guide/DOM_CACHE_GUIDE for best practices.`
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Track this key-parent relationship for future checks
|
|
88
|
+
if (currentParent) {
|
|
89
|
+
this.keyParentMap.set(key, {
|
|
90
|
+
parentTag: currentParent.tagName.toLowerCase(),
|
|
91
|
+
parentClass: currentParent.className,
|
|
92
|
+
element,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Gets a formatted parent container description.
|
|
99
|
+
*/
|
|
100
|
+
private getParentInfo(parent: Element): string {
|
|
101
|
+
const tag = parent.tagName.toLowerCase();
|
|
102
|
+
const className = parent.className;
|
|
103
|
+
return `${tag}${className ? "." + className.split(" ")[0] : ""}`;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Checks if a key exists in the cache.
|
|
108
|
+
*/
|
|
109
|
+
has(key: string): boolean {
|
|
110
|
+
return this.cache.has(key);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Clears the cache.
|
|
115
|
+
* Should be called when component is disconnected or cache is invalidated.
|
|
116
|
+
*/
|
|
117
|
+
clear(): void {
|
|
118
|
+
this.cache.clear();
|
|
119
|
+
// WeakMap doesn't need clearing
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Stores metadata for an element (e.g. previous props).
|
|
124
|
+
*/
|
|
125
|
+
setMetadata(element: Element, meta: Record<string, unknown>): void {
|
|
126
|
+
this.metadata.set(element, meta);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Retrieves metadata for an element.
|
|
131
|
+
*/
|
|
132
|
+
getMetadata(element: Element): Record<string, unknown> | undefined {
|
|
133
|
+
return this.metadata.get(element);
|
|
134
|
+
}
|
|
135
|
+
}
|