@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/index.mjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Fragment,
|
|
3
|
+
RenderContext,
|
|
4
|
+
createLogger,
|
|
3
5
|
h
|
|
4
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-AR3DIDLV.mjs";
|
|
5
7
|
|
|
6
8
|
// src/styles/style-manager.ts
|
|
7
9
|
var StyleManager = class {
|
|
@@ -44,8 +46,8 @@ var StyleManager = class {
|
|
|
44
46
|
StyleManager.styleSheets = /* @__PURE__ */ new Map();
|
|
45
47
|
|
|
46
48
|
// src/utils/reactive.ts
|
|
47
|
-
import { createLogger } from "@wsxjs/wsx-logger";
|
|
48
|
-
var logger =
|
|
49
|
+
import { createLogger as createLogger2 } from "@wsxjs/wsx-logger";
|
|
50
|
+
var logger = createLogger2("ReactiveSystem");
|
|
49
51
|
var UpdateScheduler = class {
|
|
50
52
|
constructor() {
|
|
51
53
|
this.pendingCallbacks = /* @__PURE__ */ new Set();
|
|
@@ -264,6 +266,108 @@ function reactiveWithDebug(obj, onChange, debugName) {
|
|
|
264
266
|
});
|
|
265
267
|
}
|
|
266
268
|
|
|
269
|
+
// src/dom-cache-manager.ts
|
|
270
|
+
var logger2 = createLogger("DOMCacheManager");
|
|
271
|
+
var DOMCacheManager = class {
|
|
272
|
+
constructor() {
|
|
273
|
+
// Map<CacheKey, DOMElement>
|
|
274
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
275
|
+
// Map<DOMElement, Metadata>
|
|
276
|
+
// Stores metadata (props, children) for cached elements to support diffing
|
|
277
|
+
this.metadata = /* @__PURE__ */ new WeakMap();
|
|
278
|
+
// Track key-parent relationships to detect duplicate keys in all environments
|
|
279
|
+
// Map<CacheKey, ParentInfo>
|
|
280
|
+
this.keyParentMap = /* @__PURE__ */ new Map();
|
|
281
|
+
// Flag to enable duplicate key warnings (enabled by default, critical for correctness)
|
|
282
|
+
this.warnDuplicateKeys = true;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Retrieves an element from the cache.
|
|
286
|
+
* @param key The unique cache key.
|
|
287
|
+
*/
|
|
288
|
+
get(key) {
|
|
289
|
+
return this.cache.get(key);
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Stores an element in the cache.
|
|
293
|
+
* @param key The unique cache key.
|
|
294
|
+
* @param element The DOM element to cache.
|
|
295
|
+
*/
|
|
296
|
+
set(key, element) {
|
|
297
|
+
if (this.warnDuplicateKeys) {
|
|
298
|
+
this.checkDuplicateKey(key, element);
|
|
299
|
+
}
|
|
300
|
+
this.cache.set(key, element);
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Checks if a cache key is being reused in a different parent container.
|
|
304
|
+
* Runs in all environments to help developers catch key conflicts early.
|
|
305
|
+
* This is critical for correctness and helps prevent subtle bugs.
|
|
306
|
+
*/
|
|
307
|
+
checkDuplicateKey(key, element) {
|
|
308
|
+
const existing = this.keyParentMap.get(key);
|
|
309
|
+
const currentParent = element.parentElement;
|
|
310
|
+
if (existing && currentParent) {
|
|
311
|
+
const currentParentInfo = this.getParentInfo(currentParent);
|
|
312
|
+
const existingParentInfo = `${existing.parentTag}${existing.parentClass ? "." + existing.parentClass : ""}`;
|
|
313
|
+
if (currentParentInfo !== existingParentInfo) {
|
|
314
|
+
logger2.warn(
|
|
315
|
+
`Duplicate key "${key}" detected in different parent containers!
|
|
316
|
+
Previous parent: ${existingParentInfo}
|
|
317
|
+
Current parent: ${currentParentInfo}
|
|
318
|
+
|
|
319
|
+
This may cause elements to appear in wrong containers or be moved unexpectedly.
|
|
320
|
+
|
|
321
|
+
Solution: Use unique key prefixes for different locations:
|
|
322
|
+
Example: <wsx-link key="nav-0"> vs <wsx-link key="overflow-0">
|
|
323
|
+
|
|
324
|
+
See https://wsxjs.dev/docs/guide/DOM_CACHE_GUIDE for best practices.`
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
if (currentParent) {
|
|
329
|
+
this.keyParentMap.set(key, {
|
|
330
|
+
parentTag: currentParent.tagName.toLowerCase(),
|
|
331
|
+
parentClass: currentParent.className,
|
|
332
|
+
element
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Gets a formatted parent container description.
|
|
338
|
+
*/
|
|
339
|
+
getParentInfo(parent) {
|
|
340
|
+
const tag = parent.tagName.toLowerCase();
|
|
341
|
+
const className = parent.className;
|
|
342
|
+
return `${tag}${className ? "." + className.split(" ")[0] : ""}`;
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Checks if a key exists in the cache.
|
|
346
|
+
*/
|
|
347
|
+
has(key) {
|
|
348
|
+
return this.cache.has(key);
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Clears the cache.
|
|
352
|
+
* Should be called when component is disconnected or cache is invalidated.
|
|
353
|
+
*/
|
|
354
|
+
clear() {
|
|
355
|
+
this.cache.clear();
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Stores metadata for an element (e.g. previous props).
|
|
359
|
+
*/
|
|
360
|
+
setMetadata(element, meta) {
|
|
361
|
+
this.metadata.set(element, meta);
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Retrieves metadata for an element.
|
|
365
|
+
*/
|
|
366
|
+
getMetadata(element) {
|
|
367
|
+
return this.metadata.get(element);
|
|
368
|
+
}
|
|
369
|
+
};
|
|
370
|
+
|
|
267
371
|
// src/base-component.ts
|
|
268
372
|
var BaseComponent = class extends HTMLElement {
|
|
269
373
|
constructor(config = {}) {
|
|
@@ -271,6 +375,11 @@ var BaseComponent = class extends HTMLElement {
|
|
|
271
375
|
this.connected = false;
|
|
272
376
|
this._isDebugEnabled = false;
|
|
273
377
|
this._reactiveStates = /* @__PURE__ */ new Map();
|
|
378
|
+
/**
|
|
379
|
+
* DOM Cache Manager for fine-grained updates (RFC 0037)
|
|
380
|
+
* @internal
|
|
381
|
+
*/
|
|
382
|
+
this._domCache = new DOMCacheManager();
|
|
274
383
|
/**
|
|
275
384
|
* 当前捕获的焦点状态(用于在 render 时使用捕获的值)
|
|
276
385
|
* @internal - 由 rerender() 方法管理
|
|
@@ -335,6 +444,13 @@ var BaseComponent = class extends HTMLElement {
|
|
|
335
444
|
static get observedAttributes() {
|
|
336
445
|
return [];
|
|
337
446
|
}
|
|
447
|
+
/**
|
|
448
|
+
* Gets the DOMCacheManager instance.
|
|
449
|
+
* @internal
|
|
450
|
+
*/
|
|
451
|
+
getDomCache() {
|
|
452
|
+
return this._domCache;
|
|
453
|
+
}
|
|
338
454
|
/**
|
|
339
455
|
* Web Component生命周期:属性变化
|
|
340
456
|
*/
|
|
@@ -641,8 +757,8 @@ var BaseComponent = class extends HTMLElement {
|
|
|
641
757
|
};
|
|
642
758
|
|
|
643
759
|
// src/web-component.ts
|
|
644
|
-
import { createLogger as
|
|
645
|
-
var
|
|
760
|
+
import { createLogger as createLogger3 } from "@wsxjs/wsx-logger";
|
|
761
|
+
var logger3 = createLogger3("WebComponent");
|
|
646
762
|
var WebComponent = class extends BaseComponent {
|
|
647
763
|
// Initialized by BaseComponent constructor
|
|
648
764
|
constructor(config = {}) {
|
|
@@ -691,7 +807,7 @@ var WebComponent = class extends BaseComponent {
|
|
|
691
807
|
});
|
|
692
808
|
}
|
|
693
809
|
} catch (error) {
|
|
694
|
-
|
|
810
|
+
logger3.error(`Error in connectedCallback:`, error);
|
|
695
811
|
this.renderError(error);
|
|
696
812
|
}
|
|
697
813
|
}
|
|
@@ -744,7 +860,7 @@ var WebComponent = class extends BaseComponent {
|
|
|
744
860
|
StyleManager.applyStyles(this.shadowRoot, styleName, stylesToApply);
|
|
745
861
|
}
|
|
746
862
|
}
|
|
747
|
-
const content = this.render();
|
|
863
|
+
const content = RenderContext.runInContext(this, () => this.render());
|
|
748
864
|
if (focusState && focusState.key && focusState.value !== void 0) {
|
|
749
865
|
const target = content.querySelector(
|
|
750
866
|
`[data-wsx-key="${focusState.key}"]`
|
|
@@ -772,7 +888,7 @@ var WebComponent = class extends BaseComponent {
|
|
|
772
888
|
});
|
|
773
889
|
});
|
|
774
890
|
} catch (error) {
|
|
775
|
-
|
|
891
|
+
logger3.error("Error in _rerender:", error);
|
|
776
892
|
this.renderError(error);
|
|
777
893
|
this._isRendering = false;
|
|
778
894
|
}
|
|
@@ -799,8 +915,8 @@ var WebComponent = class extends BaseComponent {
|
|
|
799
915
|
};
|
|
800
916
|
|
|
801
917
|
// src/light-component.ts
|
|
802
|
-
import { createLogger as
|
|
803
|
-
var
|
|
918
|
+
import { createLogger as createLogger4 } from "@wsxjs/wsx-logger";
|
|
919
|
+
var logger4 = createLogger4("LightComponent");
|
|
804
920
|
var LightComponent = class extends BaseComponent {
|
|
805
921
|
// Initialized by BaseComponent constructor
|
|
806
922
|
constructor(config = {}) {
|
|
@@ -842,7 +958,7 @@ var LightComponent = class extends BaseComponent {
|
|
|
842
958
|
(child) => child !== styleElement
|
|
843
959
|
);
|
|
844
960
|
childrenToRemove.forEach((child) => child.remove());
|
|
845
|
-
const content = this.render();
|
|
961
|
+
const content = RenderContext.runInContext(this, () => this.render());
|
|
846
962
|
this.appendChild(content);
|
|
847
963
|
if (styleElement && styleElement !== this.firstChild) {
|
|
848
964
|
this.insertBefore(styleElement, this.firstChild);
|
|
@@ -856,7 +972,7 @@ var LightComponent = class extends BaseComponent {
|
|
|
856
972
|
});
|
|
857
973
|
}
|
|
858
974
|
} catch (error) {
|
|
859
|
-
|
|
975
|
+
logger4.error(`[${this.constructor.name}] Error in connectedCallback:`, error);
|
|
860
976
|
this.renderError(error);
|
|
861
977
|
}
|
|
862
978
|
}
|
|
@@ -904,7 +1020,7 @@ var LightComponent = class extends BaseComponent {
|
|
|
904
1020
|
this._pendingFocusState = focusState;
|
|
905
1021
|
const jsxChildren = this.getJSXChildren();
|
|
906
1022
|
try {
|
|
907
|
-
const content = this.render();
|
|
1023
|
+
const content = RenderContext.runInContext(this, () => this.render());
|
|
908
1024
|
if (focusState && focusState.key && focusState.value !== void 0) {
|
|
909
1025
|
const target = content.querySelector(
|
|
910
1026
|
`[data-wsx-key="${focusState.key}"]`
|
|
@@ -961,7 +1077,7 @@ var LightComponent = class extends BaseComponent {
|
|
|
961
1077
|
});
|
|
962
1078
|
});
|
|
963
1079
|
} catch (error) {
|
|
964
|
-
|
|
1080
|
+
logger4.error(`[${this.constructor.name}] Error in _rerender:`, error);
|
|
965
1081
|
this.renderError(error);
|
|
966
1082
|
this._isRendering = false;
|
|
967
1083
|
}
|
|
@@ -1062,7 +1178,7 @@ function deriveTagName(className, prefix) {
|
|
|
1062
1178
|
}
|
|
1063
1179
|
|
|
1064
1180
|
// src/index.ts
|
|
1065
|
-
import { WSXLogger, logger as
|
|
1181
|
+
import { WSXLogger, logger as logger5, createLogger as createLogger5, createLoggerWithConfig } from "@wsxjs/wsx-logger";
|
|
1066
1182
|
|
|
1067
1183
|
// src/reactive-decorator.ts
|
|
1068
1184
|
function createBabelPluginError(propertyName) {
|
|
@@ -1083,6 +1199,10 @@ To fix this, please:
|
|
|
1083
1199
|
See: https://github.com/wsxjs/wsxjs#setup for more details.`;
|
|
1084
1200
|
}
|
|
1085
1201
|
function state(targetOrContext, propertyKey) {
|
|
1202
|
+
const globalProcess = typeof globalThis !== "undefined" ? globalThis.process : void 0;
|
|
1203
|
+
if (globalProcess?.env?.NODE_ENV === "test") {
|
|
1204
|
+
return;
|
|
1205
|
+
}
|
|
1086
1206
|
let propertyName = "unknown";
|
|
1087
1207
|
const propertyKeyIsObject = typeof propertyKey === "object" && propertyKey !== null;
|
|
1088
1208
|
const targetIsObject = typeof targetOrContext === "object" && targetOrContext !== null;
|
|
@@ -1143,12 +1263,12 @@ export {
|
|
|
1143
1263
|
WSXLogger,
|
|
1144
1264
|
WebComponent,
|
|
1145
1265
|
autoRegister,
|
|
1146
|
-
|
|
1266
|
+
createLogger5 as createLogger,
|
|
1147
1267
|
createLoggerWithConfig,
|
|
1148
1268
|
h,
|
|
1149
1269
|
h as jsx,
|
|
1150
1270
|
h as jsxs,
|
|
1151
|
-
|
|
1271
|
+
logger5 as logger,
|
|
1152
1272
|
registerComponent,
|
|
1153
1273
|
state
|
|
1154
1274
|
};
|