@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.js
CHANGED
|
@@ -37,6 +37,170 @@ __export(index_exports, {
|
|
|
37
37
|
});
|
|
38
38
|
module.exports = __toCommonJS(index_exports);
|
|
39
39
|
|
|
40
|
+
// src/utils/dom-utils.ts
|
|
41
|
+
function parseHTMLToNodes(html) {
|
|
42
|
+
if (!html) return [];
|
|
43
|
+
const temp = document.createElement("div");
|
|
44
|
+
temp.innerHTML = html;
|
|
45
|
+
return Array.from(temp.childNodes).map((node) => {
|
|
46
|
+
if (node instanceof HTMLElement || node instanceof SVGElement) {
|
|
47
|
+
return node;
|
|
48
|
+
} else {
|
|
49
|
+
return node.textContent || "";
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
function isHTMLString(str) {
|
|
54
|
+
const trimmed = str.trim();
|
|
55
|
+
if (!trimmed) return false;
|
|
56
|
+
const htmlTagPattern = /<[a-z][a-z0-9]*(\s[^>]*)?(\/>|>)/i;
|
|
57
|
+
const looksLikeMath = /^[^<]*<[^>]*>[^>]*$/.test(trimmed) && !htmlTagPattern.test(trimmed);
|
|
58
|
+
if (looksLikeMath) return false;
|
|
59
|
+
return htmlTagPattern.test(trimmed);
|
|
60
|
+
}
|
|
61
|
+
function flattenChildren(children, skipHTMLDetection = false, depth = 0) {
|
|
62
|
+
if (depth > 10) {
|
|
63
|
+
console.warn(
|
|
64
|
+
"[WSX] flattenChildren: Maximum depth exceeded, treating remaining children as text"
|
|
65
|
+
);
|
|
66
|
+
return children.filter(
|
|
67
|
+
(child) => typeof child === "string" || typeof child === "number"
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
const result = [];
|
|
71
|
+
for (const child of children) {
|
|
72
|
+
if (child === null || child === void 0 || child === false) {
|
|
73
|
+
continue;
|
|
74
|
+
} else if (Array.isArray(child)) {
|
|
75
|
+
result.push(...flattenChildren(child, skipHTMLDetection, depth + 1));
|
|
76
|
+
} else if (typeof child === "string") {
|
|
77
|
+
if (skipHTMLDetection) {
|
|
78
|
+
result.push(child);
|
|
79
|
+
} else if (isHTMLString(child)) {
|
|
80
|
+
try {
|
|
81
|
+
const nodes = parseHTMLToNodes(child);
|
|
82
|
+
if (nodes.length > 0) {
|
|
83
|
+
for (const node of nodes) {
|
|
84
|
+
if (typeof node === "string") {
|
|
85
|
+
result.push(node);
|
|
86
|
+
} else {
|
|
87
|
+
result.push(node);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
} else {
|
|
91
|
+
result.push(child);
|
|
92
|
+
}
|
|
93
|
+
} catch (error) {
|
|
94
|
+
console.warn("[WSX] Failed to parse HTML string, treating as text:", error);
|
|
95
|
+
result.push(child);
|
|
96
|
+
}
|
|
97
|
+
} else {
|
|
98
|
+
result.push(child);
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
result.push(child);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// src/render-context.ts
|
|
108
|
+
var _RenderContext = class _RenderContext {
|
|
109
|
+
/**
|
|
110
|
+
* Executes a function within the context of a component.
|
|
111
|
+
* @param component The component instance currently rendering.
|
|
112
|
+
* @param fn The function to execute (usually the render method).
|
|
113
|
+
*/
|
|
114
|
+
static runInContext(component, fn) {
|
|
115
|
+
const prev = _RenderContext.current;
|
|
116
|
+
_RenderContext.current = component;
|
|
117
|
+
try {
|
|
118
|
+
return fn();
|
|
119
|
+
} finally {
|
|
120
|
+
_RenderContext.current = prev;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Gets the currently rendering component.
|
|
125
|
+
*/
|
|
126
|
+
static getCurrentComponent() {
|
|
127
|
+
return _RenderContext.current;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Gets the current component's DOM cache.
|
|
131
|
+
*/
|
|
132
|
+
static getDOMCache() {
|
|
133
|
+
return _RenderContext.current?.getDomCache();
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
_RenderContext.current = null;
|
|
137
|
+
var RenderContext = _RenderContext;
|
|
138
|
+
|
|
139
|
+
// src/utils/cache-key.ts
|
|
140
|
+
var POSITION_ID_KEY = "__wsxPositionId";
|
|
141
|
+
var INDEX_KEY = "__wsxIndex";
|
|
142
|
+
var componentElementCounters = /* @__PURE__ */ new WeakMap();
|
|
143
|
+
var componentIdCache = /* @__PURE__ */ new WeakMap();
|
|
144
|
+
function generateCacheKey(tag, props, componentId, component) {
|
|
145
|
+
const positionId = props?.[POSITION_ID_KEY];
|
|
146
|
+
const userKey = props?.key;
|
|
147
|
+
const index = props?.[INDEX_KEY];
|
|
148
|
+
if (userKey !== void 0 && userKey !== null) {
|
|
149
|
+
return `${componentId}:${tag}:key-${String(userKey)}`;
|
|
150
|
+
}
|
|
151
|
+
if (index !== void 0 && index !== null) {
|
|
152
|
+
return `${componentId}:${tag}:idx-${String(index)}`;
|
|
153
|
+
}
|
|
154
|
+
if (positionId !== void 0 && positionId !== null && positionId !== "no-id") {
|
|
155
|
+
return `${componentId}:${tag}:${String(positionId)}`;
|
|
156
|
+
}
|
|
157
|
+
if (component) {
|
|
158
|
+
let counter = componentElementCounters.get(component) || 0;
|
|
159
|
+
counter++;
|
|
160
|
+
componentElementCounters.set(component, counter);
|
|
161
|
+
return `${componentId}:${tag}:auto-${counter}`;
|
|
162
|
+
}
|
|
163
|
+
return `${componentId}:${tag}:fallback-${Date.now()}-${Math.random()}`;
|
|
164
|
+
}
|
|
165
|
+
function getComponentId() {
|
|
166
|
+
const component = RenderContext.getCurrentComponent();
|
|
167
|
+
if (component) {
|
|
168
|
+
let cachedId = componentIdCache.get(component);
|
|
169
|
+
if (cachedId) {
|
|
170
|
+
return cachedId;
|
|
171
|
+
}
|
|
172
|
+
const instanceId = component._instanceId || "default";
|
|
173
|
+
cachedId = `${component.constructor.name}:${instanceId}`;
|
|
174
|
+
componentIdCache.set(component, cachedId);
|
|
175
|
+
return cachedId;
|
|
176
|
+
}
|
|
177
|
+
return "unknown";
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// src/utils/element-marking.ts
|
|
181
|
+
var CACHE_KEY_PROP = "__wsxCacheKey";
|
|
182
|
+
function markElement(element, cacheKey) {
|
|
183
|
+
element[CACHE_KEY_PROP] = cacheKey;
|
|
184
|
+
}
|
|
185
|
+
function isCreatedByH(element) {
|
|
186
|
+
if (!(element instanceof HTMLElement || element instanceof SVGElement)) {
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
return element[CACHE_KEY_PROP] !== void 0;
|
|
190
|
+
}
|
|
191
|
+
function shouldPreserveElement(element) {
|
|
192
|
+
if (!(element instanceof HTMLElement || element instanceof SVGElement)) {
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
if (!isCreatedByH(element)) {
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
if (element.hasAttribute("data-wsx-preserve")) {
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
|
|
40
204
|
// src/utils/svg-utils.ts
|
|
41
205
|
var SVG_NAMESPACE = "http://www.w3.org/2000/svg";
|
|
42
206
|
var SVG_ONLY_ELEMENTS = /* @__PURE__ */ new Set([
|
|
@@ -149,21 +313,63 @@ function getSVGAttributeName(attributeName) {
|
|
|
149
313
|
return SVG_ATTRIBUTE_MAP.get(attributeName) || attributeName;
|
|
150
314
|
}
|
|
151
315
|
|
|
152
|
-
// src/utils/
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
316
|
+
// src/utils/logger.ts
|
|
317
|
+
var WSXLogger = class {
|
|
318
|
+
constructor(prefix = "[WSX]", enabled = true, level = "info") {
|
|
319
|
+
this.prefix = prefix;
|
|
320
|
+
this.enabled = enabled;
|
|
321
|
+
this.level = level;
|
|
322
|
+
}
|
|
323
|
+
shouldLog(level) {
|
|
324
|
+
if (!this.enabled) return false;
|
|
325
|
+
const levels = ["debug", "info", "warn", "error"];
|
|
326
|
+
const currentLevelIndex = levels.indexOf(this.level);
|
|
327
|
+
const messageLevelIndex = levels.indexOf(level);
|
|
328
|
+
return messageLevelIndex >= currentLevelIndex;
|
|
329
|
+
}
|
|
330
|
+
debug(message, ...args) {
|
|
331
|
+
if (this.shouldLog("debug")) {
|
|
332
|
+
console.debug(`${this.prefix} ${message}`, ...args);
|
|
162
333
|
}
|
|
163
|
-
}
|
|
334
|
+
}
|
|
335
|
+
info(message, ...args) {
|
|
336
|
+
if (this.shouldLog("info")) {
|
|
337
|
+
console.info(`${this.prefix} ${message}`, ...args);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
warn(message, ...args) {
|
|
341
|
+
if (this.shouldLog("warn")) {
|
|
342
|
+
console.warn(`${this.prefix} ${message}`, ...args);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
error(message, ...args) {
|
|
346
|
+
if (this.shouldLog("error")) {
|
|
347
|
+
console.error(`${this.prefix} ${message}`, ...args);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
var logger = new WSXLogger();
|
|
352
|
+
function createLogger(componentName) {
|
|
353
|
+
return new WSXLogger(`[WSX:${componentName}]`);
|
|
164
354
|
}
|
|
165
355
|
|
|
166
|
-
// src/
|
|
356
|
+
// src/utils/props-utils.ts
|
|
357
|
+
var logger2 = createLogger("Props Utilities");
|
|
358
|
+
function isFrameworkInternalProp(key) {
|
|
359
|
+
if (key === "key") {
|
|
360
|
+
return true;
|
|
361
|
+
}
|
|
362
|
+
if (key === "__wsxPositionId" || key === "__wsxIndex") {
|
|
363
|
+
return true;
|
|
364
|
+
}
|
|
365
|
+
if (key === "__testId") {
|
|
366
|
+
return true;
|
|
367
|
+
}
|
|
368
|
+
if (key === "ref") {
|
|
369
|
+
return true;
|
|
370
|
+
}
|
|
371
|
+
return false;
|
|
372
|
+
}
|
|
167
373
|
function isStandardHTMLAttribute(key) {
|
|
168
374
|
const standardAttributes = /* @__PURE__ */ new Set([
|
|
169
375
|
// 全局属性
|
|
@@ -246,7 +452,8 @@ function isStandardHTMLAttribute(key) {
|
|
|
246
452
|
function isSpecialProperty(key, value) {
|
|
247
453
|
return key === "ref" || key === "className" || key === "class" || key === "style" || key.startsWith("on") && typeof value === "function" || typeof value === "boolean" || key === "value";
|
|
248
454
|
}
|
|
249
|
-
function setSmartProperty(element, key, value,
|
|
455
|
+
function setSmartProperty(element, key, value, tag) {
|
|
456
|
+
const isSVG = shouldUseSVGNamespace(tag);
|
|
250
457
|
if (isSpecialProperty(key, value)) {
|
|
251
458
|
return;
|
|
252
459
|
}
|
|
@@ -256,13 +463,13 @@ function setSmartProperty(element, key, value, isSVG = false) {
|
|
|
256
463
|
try {
|
|
257
464
|
const serialized = JSON.stringify(value);
|
|
258
465
|
if (serialized.length > 1024 * 1024) {
|
|
259
|
-
|
|
466
|
+
logger2.warn(
|
|
260
467
|
`[WSX] Attribute "${key}" value too large, consider using a non-standard property name instead`
|
|
261
468
|
);
|
|
262
469
|
}
|
|
263
470
|
element.setAttribute(attributeName, serialized);
|
|
264
471
|
} catch (error) {
|
|
265
|
-
|
|
472
|
+
logger2.warn(`Cannot serialize attribute "${key}":`, error);
|
|
266
473
|
}
|
|
267
474
|
} else {
|
|
268
475
|
element.setAttribute(attributeName, String(value));
|
|
@@ -276,7 +483,7 @@ function setSmartProperty(element, key, value, isSVG = false) {
|
|
|
276
483
|
const serialized = JSON.stringify(value);
|
|
277
484
|
element.setAttribute(attributeName, serialized);
|
|
278
485
|
} catch (error) {
|
|
279
|
-
|
|
486
|
+
logger2.warn(`Cannot serialize SVG attribute "${key}":`, error);
|
|
280
487
|
}
|
|
281
488
|
} else {
|
|
282
489
|
element.setAttribute(attributeName, String(value));
|
|
@@ -300,7 +507,7 @@ function setSmartProperty(element, key, value, isSVG = false) {
|
|
|
300
507
|
const serialized = JSON.stringify(value);
|
|
301
508
|
element.setAttribute(attributeName, serialized);
|
|
302
509
|
} catch (error) {
|
|
303
|
-
|
|
510
|
+
logger2.warn(`Cannot serialize readonly property "${key}":`, error);
|
|
304
511
|
}
|
|
305
512
|
} else {
|
|
306
513
|
element.setAttribute(attributeName, String(value));
|
|
@@ -315,7 +522,7 @@ function setSmartProperty(element, key, value, isSVG = false) {
|
|
|
315
522
|
const serialized = JSON.stringify(value);
|
|
316
523
|
element.setAttribute(attributeName, serialized);
|
|
317
524
|
} catch (error) {
|
|
318
|
-
|
|
525
|
+
logger2.warn(
|
|
319
526
|
`[WSX] Cannot serialize property "${key}" for attribute:`,
|
|
320
527
|
error
|
|
321
528
|
);
|
|
@@ -331,59 +538,76 @@ function setSmartProperty(element, key, value, isSVG = false) {
|
|
|
331
538
|
try {
|
|
332
539
|
const serialized = JSON.stringify(value);
|
|
333
540
|
if (serialized.length > 1024 * 1024) {
|
|
334
|
-
|
|
541
|
+
logger2.warn(
|
|
335
542
|
`[WSX] Property "${key}" value too large for attribute, consider using a JavaScript property instead`
|
|
336
543
|
);
|
|
337
544
|
}
|
|
338
545
|
element.setAttribute(attributeName, serialized);
|
|
339
546
|
} catch (error) {
|
|
340
|
-
|
|
547
|
+
logger2.warn(`Cannot serialize property "${key}" for attribute:`, error);
|
|
341
548
|
}
|
|
342
549
|
} else {
|
|
343
550
|
element.setAttribute(attributeName, String(value));
|
|
344
551
|
}
|
|
345
552
|
}
|
|
346
553
|
}
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
554
|
+
|
|
555
|
+
// src/utils/element-creation.ts
|
|
556
|
+
function applySingleProp(element, key, value, tag, isSVG) {
|
|
557
|
+
if (value === null || value === void 0 || value === false) {
|
|
558
|
+
return;
|
|
350
559
|
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
560
|
+
if (key === "ref" && typeof value === "function") {
|
|
561
|
+
value(element);
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
564
|
+
if (key === "className" || key === "class") {
|
|
565
|
+
if (isSVG) {
|
|
566
|
+
element.setAttribute("class", value);
|
|
567
|
+
} else {
|
|
568
|
+
element.className = value;
|
|
569
|
+
}
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
572
|
+
if (key === "style" && typeof value === "string") {
|
|
573
|
+
element.setAttribute("style", value);
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
if (key.startsWith("on") && typeof value === "function") {
|
|
577
|
+
const eventName = key.slice(2).toLowerCase();
|
|
578
|
+
element.addEventListener(eventName, value);
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
581
|
+
if (typeof value === "boolean") {
|
|
582
|
+
if (value) {
|
|
583
|
+
element.setAttribute(key, "");
|
|
584
|
+
}
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
if (key === "value") {
|
|
588
|
+
if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element instanceof HTMLSelectElement) {
|
|
589
|
+
element.value = String(value);
|
|
590
|
+
} else {
|
|
591
|
+
const attributeName = isSVG ? getSVGAttributeName(key) : key;
|
|
592
|
+
element.setAttribute(attributeName, String(value));
|
|
593
|
+
}
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
if (isFrameworkInternalProp(key)) {
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
599
|
+
setSmartProperty(element, key, value, tag);
|
|
600
|
+
}
|
|
601
|
+
function applyPropsToElement(element, props, tag) {
|
|
602
|
+
if (!props) {
|
|
603
|
+
return;
|
|
386
604
|
}
|
|
605
|
+
const isSVG = shouldUseSVGNamespace(tag);
|
|
606
|
+
Object.entries(props).forEach(([key, value]) => {
|
|
607
|
+
applySingleProp(element, key, value, tag, isSVG);
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
function appendChildrenToElement(element, children) {
|
|
387
611
|
const flatChildren = flattenChildren(children);
|
|
388
612
|
flatChildren.forEach((child) => {
|
|
389
613
|
if (child === null || child === void 0 || child === false) {
|
|
@@ -397,60 +621,278 @@ function h(tag, props = {}, ...children) {
|
|
|
397
621
|
element.appendChild(child);
|
|
398
622
|
}
|
|
399
623
|
});
|
|
624
|
+
}
|
|
625
|
+
function createElementWithPropsAndChildren(tag, props, children) {
|
|
626
|
+
const element = createElement(tag);
|
|
627
|
+
applyPropsToElement(element, props, tag);
|
|
628
|
+
appendChildrenToElement(element, children);
|
|
400
629
|
return element;
|
|
401
630
|
}
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
const
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
631
|
+
|
|
632
|
+
// src/utils/element-update.ts
|
|
633
|
+
function removeProp(element, key, oldValue, tag) {
|
|
634
|
+
const isSVG = shouldUseSVGNamespace(tag);
|
|
635
|
+
if (key === "ref") {
|
|
636
|
+
return;
|
|
637
|
+
}
|
|
638
|
+
if (key === "className" || key === "class") {
|
|
639
|
+
if (isSVG) {
|
|
640
|
+
element.removeAttribute("class");
|
|
641
|
+
} else {
|
|
642
|
+
element.className = "";
|
|
643
|
+
}
|
|
644
|
+
return;
|
|
645
|
+
}
|
|
646
|
+
if (key === "style") {
|
|
647
|
+
element.removeAttribute("style");
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
if (key.startsWith("on") && typeof oldValue === "function") {
|
|
651
|
+
return;
|
|
652
|
+
}
|
|
653
|
+
if (key === "value") {
|
|
654
|
+
if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element instanceof HTMLSelectElement) {
|
|
655
|
+
element.value = "";
|
|
656
|
+
} else {
|
|
657
|
+
const attributeName2 = isSVG ? getSVGAttributeName(key) : key;
|
|
658
|
+
element.removeAttribute(attributeName2);
|
|
659
|
+
}
|
|
660
|
+
return;
|
|
661
|
+
}
|
|
662
|
+
if (isFrameworkInternalProp(key)) {
|
|
663
|
+
return;
|
|
664
|
+
}
|
|
665
|
+
const attributeName = isSVG ? getSVGAttributeName(key) : key;
|
|
666
|
+
element.removeAttribute(attributeName);
|
|
667
|
+
try {
|
|
668
|
+
delete element[key];
|
|
669
|
+
} catch {
|
|
670
|
+
}
|
|
409
671
|
}
|
|
410
|
-
function
|
|
411
|
-
if (
|
|
412
|
-
|
|
413
|
-
"[WSX] flattenChildren: Maximum depth exceeded, treating remaining children as text"
|
|
414
|
-
);
|
|
415
|
-
return children.filter(
|
|
416
|
-
(child) => typeof child === "string" || typeof child === "number"
|
|
417
|
-
);
|
|
672
|
+
function applySingleProp2(element, key, value, tag, isSVG) {
|
|
673
|
+
if (value === null || value === void 0 || value === false) {
|
|
674
|
+
return;
|
|
418
675
|
}
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
676
|
+
if (key === "ref" && typeof value === "function") {
|
|
677
|
+
value(element);
|
|
678
|
+
return;
|
|
679
|
+
}
|
|
680
|
+
if (key === "className" || key === "class") {
|
|
681
|
+
if (isSVG) {
|
|
682
|
+
element.setAttribute("class", value);
|
|
683
|
+
} else {
|
|
684
|
+
element.className = value;
|
|
685
|
+
}
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
if (key === "style" && typeof value === "string") {
|
|
689
|
+
element.setAttribute("style", value);
|
|
690
|
+
return;
|
|
691
|
+
}
|
|
692
|
+
if (key.startsWith("on") && typeof value === "function") {
|
|
693
|
+
const eventName = key.slice(2).toLowerCase();
|
|
694
|
+
element.addEventListener(eventName, value);
|
|
695
|
+
return;
|
|
696
|
+
}
|
|
697
|
+
if (typeof value === "boolean") {
|
|
698
|
+
if (value) {
|
|
699
|
+
element.setAttribute(key, "");
|
|
700
|
+
}
|
|
701
|
+
return;
|
|
702
|
+
}
|
|
703
|
+
if (key === "value") {
|
|
704
|
+
if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element instanceof HTMLSelectElement) {
|
|
705
|
+
element.value = String(value);
|
|
706
|
+
} else {
|
|
707
|
+
const attributeName = isSVG ? getSVGAttributeName(key) : key;
|
|
708
|
+
element.setAttribute(attributeName, String(value));
|
|
709
|
+
}
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
if (isFrameworkInternalProp(key)) {
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
715
|
+
setSmartProperty(element, key, value, tag);
|
|
716
|
+
}
|
|
717
|
+
function updateProps(element, oldProps, newProps, tag) {
|
|
718
|
+
const isSVG = shouldUseSVGNamespace(tag);
|
|
719
|
+
const old = oldProps || {};
|
|
720
|
+
const new_ = newProps || {};
|
|
721
|
+
for (const key in old) {
|
|
722
|
+
if (!(key in new_)) {
|
|
723
|
+
removeProp(element, key, old[key], tag);
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
for (const key in new_) {
|
|
727
|
+
const oldValue = old[key];
|
|
728
|
+
const newValue = new_[key];
|
|
729
|
+
if (oldValue === newValue) {
|
|
422
730
|
continue;
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
731
|
+
}
|
|
732
|
+
if (typeof oldValue === "object" && oldValue !== null && typeof newValue === "object" && newValue !== null) {
|
|
733
|
+
if (JSON.stringify(oldValue) === JSON.stringify(newValue)) {
|
|
734
|
+
continue;
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
applySingleProp2(element, key, newValue, tag, isSVG);
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
function updateChildren(element, oldChildren, newChildren) {
|
|
741
|
+
const flatOld = flattenChildren(oldChildren);
|
|
742
|
+
const flatNew = flattenChildren(newChildren);
|
|
743
|
+
const minLength = Math.min(flatOld.length, flatNew.length);
|
|
744
|
+
for (let i = 0; i < minLength; i++) {
|
|
745
|
+
const oldChild = flatOld[i];
|
|
746
|
+
const newChild = flatNew[i];
|
|
747
|
+
if (typeof oldChild === "string" || typeof oldChild === "number") {
|
|
748
|
+
if (typeof newChild === "string" || typeof newChild === "number") {
|
|
749
|
+
const textNode = element.childNodes[i];
|
|
750
|
+
if (textNode && textNode.nodeType === Node.TEXT_NODE) {
|
|
751
|
+
textNode.textContent = String(newChild);
|
|
752
|
+
} else {
|
|
753
|
+
const newTextNode = document.createTextNode(String(newChild));
|
|
754
|
+
if (textNode) {
|
|
755
|
+
element.replaceChild(newTextNode, textNode);
|
|
756
|
+
} else {
|
|
757
|
+
element.appendChild(newTextNode);
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
} else {
|
|
761
|
+
const textNode = element.childNodes[i];
|
|
762
|
+
if (textNode) {
|
|
763
|
+
if (!shouldPreserveElement(textNode)) {
|
|
764
|
+
element.removeChild(textNode);
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
if (typeof newChild === "string" || typeof newChild === "number") {
|
|
768
|
+
element.appendChild(document.createTextNode(String(newChild)));
|
|
769
|
+
} else if (newChild instanceof HTMLElement || newChild instanceof SVGElement) {
|
|
770
|
+
element.appendChild(newChild);
|
|
771
|
+
} else if (newChild instanceof DocumentFragment) {
|
|
772
|
+
element.appendChild(newChild);
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
} else if (oldChild instanceof HTMLElement || oldChild instanceof SVGElement) {
|
|
776
|
+
if (newChild === oldChild) {
|
|
777
|
+
continue;
|
|
778
|
+
} else if (newChild instanceof HTMLElement || newChild instanceof SVGElement) {
|
|
779
|
+
const oldNode = element.childNodes[i];
|
|
780
|
+
if (oldNode) {
|
|
781
|
+
if (!shouldPreserveElement(oldNode)) {
|
|
782
|
+
if (oldNode !== newChild) {
|
|
783
|
+
element.replaceChild(newChild, oldNode);
|
|
438
784
|
}
|
|
439
785
|
} else {
|
|
440
|
-
|
|
786
|
+
if (newChild.parentNode !== element) {
|
|
787
|
+
element.appendChild(newChild);
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
} else {
|
|
791
|
+
if (newChild.parentNode !== element) {
|
|
792
|
+
element.appendChild(newChild);
|
|
441
793
|
}
|
|
442
|
-
} catch (error) {
|
|
443
|
-
console.warn("[WSX] Failed to parse HTML string, treating as text:", error);
|
|
444
|
-
result.push(child);
|
|
445
794
|
}
|
|
446
795
|
} else {
|
|
447
|
-
|
|
796
|
+
const oldNode = element.childNodes[i];
|
|
797
|
+
if (oldNode) {
|
|
798
|
+
if (!shouldPreserveElement(oldNode)) {
|
|
799
|
+
element.removeChild(oldNode);
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
if (typeof newChild === "string" || typeof newChild === "number") {
|
|
803
|
+
element.appendChild(document.createTextNode(String(newChild)));
|
|
804
|
+
} else if (newChild instanceof DocumentFragment) {
|
|
805
|
+
element.appendChild(newChild);
|
|
806
|
+
}
|
|
448
807
|
}
|
|
449
|
-
} else {
|
|
450
|
-
result.push(child);
|
|
451
808
|
}
|
|
452
809
|
}
|
|
453
|
-
|
|
810
|
+
for (let i = minLength; i < flatNew.length; i++) {
|
|
811
|
+
const newChild = flatNew[i];
|
|
812
|
+
if (newChild === null || newChild === void 0 || newChild === false) {
|
|
813
|
+
continue;
|
|
814
|
+
}
|
|
815
|
+
if (typeof newChild === "string" || typeof newChild === "number") {
|
|
816
|
+
element.appendChild(document.createTextNode(String(newChild)));
|
|
817
|
+
} else if (newChild instanceof HTMLElement || newChild instanceof SVGElement) {
|
|
818
|
+
if (newChild.parentNode !== element) {
|
|
819
|
+
element.appendChild(newChild);
|
|
820
|
+
}
|
|
821
|
+
} else if (newChild instanceof DocumentFragment) {
|
|
822
|
+
element.appendChild(newChild);
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
const nodesToRemove = [];
|
|
826
|
+
for (let i = flatNew.length; i < element.childNodes.length; i++) {
|
|
827
|
+
const child = element.childNodes[i];
|
|
828
|
+
if (!shouldPreserveElement(child)) {
|
|
829
|
+
nodesToRemove.push(child);
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
for (let i = nodesToRemove.length - 1; i >= 0; i--) {
|
|
833
|
+
const node = nodesToRemove[i];
|
|
834
|
+
if (node.parentNode === element) {
|
|
835
|
+
element.removeChild(node);
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
function updateElement(element, newProps, newChildren, tag, cacheManager) {
|
|
840
|
+
const oldMetadata = cacheManager.getMetadata(element);
|
|
841
|
+
const oldProps = oldMetadata?.props || null;
|
|
842
|
+
const oldChildren = oldMetadata?.children || [];
|
|
843
|
+
updateProps(element, oldProps, newProps, tag);
|
|
844
|
+
updateChildren(element, oldChildren, newChildren);
|
|
845
|
+
cacheManager.setMetadata(element, {
|
|
846
|
+
props: newProps || {},
|
|
847
|
+
children: newChildren
|
|
848
|
+
});
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
// src/jsx-factory.ts
|
|
852
|
+
var logger3 = createLogger("JSX Factory");
|
|
853
|
+
function h(tag, props = {}, ...children) {
|
|
854
|
+
if (typeof tag === "function") {
|
|
855
|
+
return tag(props, children);
|
|
856
|
+
}
|
|
857
|
+
const context = RenderContext.getCurrentComponent();
|
|
858
|
+
const cacheManager = context ? RenderContext.getDOMCache() : null;
|
|
859
|
+
if (context && cacheManager) {
|
|
860
|
+
return tryUseCacheOrCreate(tag, props, children, context, cacheManager);
|
|
861
|
+
}
|
|
862
|
+
return createElementWithPropsAndChildren(tag, props, children);
|
|
863
|
+
}
|
|
864
|
+
function tryUseCacheOrCreate(tag, props, children, context, cacheManager) {
|
|
865
|
+
try {
|
|
866
|
+
const componentId = getComponentId();
|
|
867
|
+
const cacheKey = generateCacheKey(tag, props, componentId, context);
|
|
868
|
+
const cachedElement = cacheManager.get(cacheKey);
|
|
869
|
+
if (cachedElement) {
|
|
870
|
+
const element2 = cachedElement;
|
|
871
|
+
updateElement(element2, props, children, tag, cacheManager);
|
|
872
|
+
return element2;
|
|
873
|
+
}
|
|
874
|
+
const element = createElementWithPropsAndChildren(tag, props, children);
|
|
875
|
+
cacheManager.set(cacheKey, element);
|
|
876
|
+
markElement(element, cacheKey);
|
|
877
|
+
cacheManager.setMetadata(element, {
|
|
878
|
+
props: props || {},
|
|
879
|
+
children
|
|
880
|
+
});
|
|
881
|
+
return element;
|
|
882
|
+
} catch (error) {
|
|
883
|
+
return handleCacheError(error, tag, props, children);
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
function handleCacheError(error, tag, props, children) {
|
|
887
|
+
try {
|
|
888
|
+
const nodeEnv = typeof globalThis.process !== "undefined" && // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
889
|
+
globalThis.process.env?.NODE_ENV;
|
|
890
|
+
if (nodeEnv === "development") {
|
|
891
|
+
logger3.warn("[WSX DOM Cache] Cache error, falling back to create new element:", error);
|
|
892
|
+
}
|
|
893
|
+
} catch {
|
|
894
|
+
}
|
|
895
|
+
return createElementWithPropsAndChildren(tag, props, children);
|
|
454
896
|
}
|
|
455
897
|
function Fragment(_props, children) {
|
|
456
898
|
const fragment = document.createDocumentFragment();
|
|
@@ -512,7 +954,7 @@ StyleManager.styleSheets = /* @__PURE__ */ new Map();
|
|
|
512
954
|
|
|
513
955
|
// src/utils/reactive.ts
|
|
514
956
|
var import_wsx_logger = require("@wsxjs/wsx-logger");
|
|
515
|
-
var
|
|
957
|
+
var logger4 = (0, import_wsx_logger.createLogger)("ReactiveSystem");
|
|
516
958
|
var UpdateScheduler = class {
|
|
517
959
|
constructor() {
|
|
518
960
|
this.pendingCallbacks = /* @__PURE__ */ new Set();
|
|
@@ -541,7 +983,7 @@ var UpdateScheduler = class {
|
|
|
541
983
|
try {
|
|
542
984
|
callback();
|
|
543
985
|
} catch (error) {
|
|
544
|
-
|
|
986
|
+
logger4.error("[WSX Reactive] Error in callback:", error);
|
|
545
987
|
}
|
|
546
988
|
});
|
|
547
989
|
}
|
|
@@ -683,7 +1125,7 @@ var ReactiveDebug = {
|
|
|
683
1125
|
*/
|
|
684
1126
|
log(message, ...args) {
|
|
685
1127
|
if (this.isEnabled()) {
|
|
686
|
-
|
|
1128
|
+
logger4.info(`[WSX Reactive] ${message}`, ...args);
|
|
687
1129
|
}
|
|
688
1130
|
}
|
|
689
1131
|
};
|
|
@@ -731,6 +1173,108 @@ function reactiveWithDebug(obj, onChange, debugName) {
|
|
|
731
1173
|
});
|
|
732
1174
|
}
|
|
733
1175
|
|
|
1176
|
+
// src/dom-cache-manager.ts
|
|
1177
|
+
var logger5 = createLogger("DOMCacheManager");
|
|
1178
|
+
var DOMCacheManager = class {
|
|
1179
|
+
constructor() {
|
|
1180
|
+
// Map<CacheKey, DOMElement>
|
|
1181
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
1182
|
+
// Map<DOMElement, Metadata>
|
|
1183
|
+
// Stores metadata (props, children) for cached elements to support diffing
|
|
1184
|
+
this.metadata = /* @__PURE__ */ new WeakMap();
|
|
1185
|
+
// Track key-parent relationships to detect duplicate keys in all environments
|
|
1186
|
+
// Map<CacheKey, ParentInfo>
|
|
1187
|
+
this.keyParentMap = /* @__PURE__ */ new Map();
|
|
1188
|
+
// Flag to enable duplicate key warnings (enabled by default, critical for correctness)
|
|
1189
|
+
this.warnDuplicateKeys = true;
|
|
1190
|
+
}
|
|
1191
|
+
/**
|
|
1192
|
+
* Retrieves an element from the cache.
|
|
1193
|
+
* @param key The unique cache key.
|
|
1194
|
+
*/
|
|
1195
|
+
get(key) {
|
|
1196
|
+
return this.cache.get(key);
|
|
1197
|
+
}
|
|
1198
|
+
/**
|
|
1199
|
+
* Stores an element in the cache.
|
|
1200
|
+
* @param key The unique cache key.
|
|
1201
|
+
* @param element The DOM element to cache.
|
|
1202
|
+
*/
|
|
1203
|
+
set(key, element) {
|
|
1204
|
+
if (this.warnDuplicateKeys) {
|
|
1205
|
+
this.checkDuplicateKey(key, element);
|
|
1206
|
+
}
|
|
1207
|
+
this.cache.set(key, element);
|
|
1208
|
+
}
|
|
1209
|
+
/**
|
|
1210
|
+
* Checks if a cache key is being reused in a different parent container.
|
|
1211
|
+
* Runs in all environments to help developers catch key conflicts early.
|
|
1212
|
+
* This is critical for correctness and helps prevent subtle bugs.
|
|
1213
|
+
*/
|
|
1214
|
+
checkDuplicateKey(key, element) {
|
|
1215
|
+
const existing = this.keyParentMap.get(key);
|
|
1216
|
+
const currentParent = element.parentElement;
|
|
1217
|
+
if (existing && currentParent) {
|
|
1218
|
+
const currentParentInfo = this.getParentInfo(currentParent);
|
|
1219
|
+
const existingParentInfo = `${existing.parentTag}${existing.parentClass ? "." + existing.parentClass : ""}`;
|
|
1220
|
+
if (currentParentInfo !== existingParentInfo) {
|
|
1221
|
+
logger5.warn(
|
|
1222
|
+
`Duplicate key "${key}" detected in different parent containers!
|
|
1223
|
+
Previous parent: ${existingParentInfo}
|
|
1224
|
+
Current parent: ${currentParentInfo}
|
|
1225
|
+
|
|
1226
|
+
This may cause elements to appear in wrong containers or be moved unexpectedly.
|
|
1227
|
+
|
|
1228
|
+
Solution: Use unique key prefixes for different locations:
|
|
1229
|
+
Example: <wsx-link key="nav-0"> vs <wsx-link key="overflow-0">
|
|
1230
|
+
|
|
1231
|
+
See https://wsxjs.dev/docs/guide/DOM_CACHE_GUIDE for best practices.`
|
|
1232
|
+
);
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
if (currentParent) {
|
|
1236
|
+
this.keyParentMap.set(key, {
|
|
1237
|
+
parentTag: currentParent.tagName.toLowerCase(),
|
|
1238
|
+
parentClass: currentParent.className,
|
|
1239
|
+
element
|
|
1240
|
+
});
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
/**
|
|
1244
|
+
* Gets a formatted parent container description.
|
|
1245
|
+
*/
|
|
1246
|
+
getParentInfo(parent) {
|
|
1247
|
+
const tag = parent.tagName.toLowerCase();
|
|
1248
|
+
const className = parent.className;
|
|
1249
|
+
return `${tag}${className ? "." + className.split(" ")[0] : ""}`;
|
|
1250
|
+
}
|
|
1251
|
+
/**
|
|
1252
|
+
* Checks if a key exists in the cache.
|
|
1253
|
+
*/
|
|
1254
|
+
has(key) {
|
|
1255
|
+
return this.cache.has(key);
|
|
1256
|
+
}
|
|
1257
|
+
/**
|
|
1258
|
+
* Clears the cache.
|
|
1259
|
+
* Should be called when component is disconnected or cache is invalidated.
|
|
1260
|
+
*/
|
|
1261
|
+
clear() {
|
|
1262
|
+
this.cache.clear();
|
|
1263
|
+
}
|
|
1264
|
+
/**
|
|
1265
|
+
* Stores metadata for an element (e.g. previous props).
|
|
1266
|
+
*/
|
|
1267
|
+
setMetadata(element, meta) {
|
|
1268
|
+
this.metadata.set(element, meta);
|
|
1269
|
+
}
|
|
1270
|
+
/**
|
|
1271
|
+
* Retrieves metadata for an element.
|
|
1272
|
+
*/
|
|
1273
|
+
getMetadata(element) {
|
|
1274
|
+
return this.metadata.get(element);
|
|
1275
|
+
}
|
|
1276
|
+
};
|
|
1277
|
+
|
|
734
1278
|
// src/base-component.ts
|
|
735
1279
|
var BaseComponent = class extends HTMLElement {
|
|
736
1280
|
constructor(config = {}) {
|
|
@@ -738,6 +1282,11 @@ var BaseComponent = class extends HTMLElement {
|
|
|
738
1282
|
this.connected = false;
|
|
739
1283
|
this._isDebugEnabled = false;
|
|
740
1284
|
this._reactiveStates = /* @__PURE__ */ new Map();
|
|
1285
|
+
/**
|
|
1286
|
+
* DOM Cache Manager for fine-grained updates (RFC 0037)
|
|
1287
|
+
* @internal
|
|
1288
|
+
*/
|
|
1289
|
+
this._domCache = new DOMCacheManager();
|
|
741
1290
|
/**
|
|
742
1291
|
* 当前捕获的焦点状态(用于在 render 时使用捕获的值)
|
|
743
1292
|
* @internal - 由 rerender() 方法管理
|
|
@@ -802,6 +1351,13 @@ var BaseComponent = class extends HTMLElement {
|
|
|
802
1351
|
static get observedAttributes() {
|
|
803
1352
|
return [];
|
|
804
1353
|
}
|
|
1354
|
+
/**
|
|
1355
|
+
* Gets the DOMCacheManager instance.
|
|
1356
|
+
* @internal
|
|
1357
|
+
*/
|
|
1358
|
+
getDomCache() {
|
|
1359
|
+
return this._domCache;
|
|
1360
|
+
}
|
|
805
1361
|
/**
|
|
806
1362
|
* Web Component生命周期:属性变化
|
|
807
1363
|
*/
|
|
@@ -1109,7 +1665,7 @@ var BaseComponent = class extends HTMLElement {
|
|
|
1109
1665
|
|
|
1110
1666
|
// src/web-component.ts
|
|
1111
1667
|
var import_wsx_logger2 = require("@wsxjs/wsx-logger");
|
|
1112
|
-
var
|
|
1668
|
+
var logger6 = (0, import_wsx_logger2.createLogger)("WebComponent");
|
|
1113
1669
|
var WebComponent = class extends BaseComponent {
|
|
1114
1670
|
// Initialized by BaseComponent constructor
|
|
1115
1671
|
constructor(config = {}) {
|
|
@@ -1158,7 +1714,7 @@ var WebComponent = class extends BaseComponent {
|
|
|
1158
1714
|
});
|
|
1159
1715
|
}
|
|
1160
1716
|
} catch (error) {
|
|
1161
|
-
|
|
1717
|
+
logger6.error(`Error in connectedCallback:`, error);
|
|
1162
1718
|
this.renderError(error);
|
|
1163
1719
|
}
|
|
1164
1720
|
}
|
|
@@ -1211,7 +1767,7 @@ var WebComponent = class extends BaseComponent {
|
|
|
1211
1767
|
StyleManager.applyStyles(this.shadowRoot, styleName, stylesToApply);
|
|
1212
1768
|
}
|
|
1213
1769
|
}
|
|
1214
|
-
const content = this.render();
|
|
1770
|
+
const content = RenderContext.runInContext(this, () => this.render());
|
|
1215
1771
|
if (focusState && focusState.key && focusState.value !== void 0) {
|
|
1216
1772
|
const target = content.querySelector(
|
|
1217
1773
|
`[data-wsx-key="${focusState.key}"]`
|
|
@@ -1239,7 +1795,7 @@ var WebComponent = class extends BaseComponent {
|
|
|
1239
1795
|
});
|
|
1240
1796
|
});
|
|
1241
1797
|
} catch (error) {
|
|
1242
|
-
|
|
1798
|
+
logger6.error("Error in _rerender:", error);
|
|
1243
1799
|
this.renderError(error);
|
|
1244
1800
|
this._isRendering = false;
|
|
1245
1801
|
}
|
|
@@ -1267,7 +1823,7 @@ var WebComponent = class extends BaseComponent {
|
|
|
1267
1823
|
|
|
1268
1824
|
// src/light-component.ts
|
|
1269
1825
|
var import_wsx_logger3 = require("@wsxjs/wsx-logger");
|
|
1270
|
-
var
|
|
1826
|
+
var logger7 = (0, import_wsx_logger3.createLogger)("LightComponent");
|
|
1271
1827
|
var LightComponent = class extends BaseComponent {
|
|
1272
1828
|
// Initialized by BaseComponent constructor
|
|
1273
1829
|
constructor(config = {}) {
|
|
@@ -1309,7 +1865,7 @@ var LightComponent = class extends BaseComponent {
|
|
|
1309
1865
|
(child) => child !== styleElement
|
|
1310
1866
|
);
|
|
1311
1867
|
childrenToRemove.forEach((child) => child.remove());
|
|
1312
|
-
const content = this.render();
|
|
1868
|
+
const content = RenderContext.runInContext(this, () => this.render());
|
|
1313
1869
|
this.appendChild(content);
|
|
1314
1870
|
if (styleElement && styleElement !== this.firstChild) {
|
|
1315
1871
|
this.insertBefore(styleElement, this.firstChild);
|
|
@@ -1323,7 +1879,7 @@ var LightComponent = class extends BaseComponent {
|
|
|
1323
1879
|
});
|
|
1324
1880
|
}
|
|
1325
1881
|
} catch (error) {
|
|
1326
|
-
|
|
1882
|
+
logger7.error(`[${this.constructor.name}] Error in connectedCallback:`, error);
|
|
1327
1883
|
this.renderError(error);
|
|
1328
1884
|
}
|
|
1329
1885
|
}
|
|
@@ -1371,7 +1927,7 @@ var LightComponent = class extends BaseComponent {
|
|
|
1371
1927
|
this._pendingFocusState = focusState;
|
|
1372
1928
|
const jsxChildren = this.getJSXChildren();
|
|
1373
1929
|
try {
|
|
1374
|
-
const content = this.render();
|
|
1930
|
+
const content = RenderContext.runInContext(this, () => this.render());
|
|
1375
1931
|
if (focusState && focusState.key && focusState.value !== void 0) {
|
|
1376
1932
|
const target = content.querySelector(
|
|
1377
1933
|
`[data-wsx-key="${focusState.key}"]`
|
|
@@ -1428,7 +1984,7 @@ var LightComponent = class extends BaseComponent {
|
|
|
1428
1984
|
});
|
|
1429
1985
|
});
|
|
1430
1986
|
} catch (error) {
|
|
1431
|
-
|
|
1987
|
+
logger7.error(`[${this.constructor.name}] Error in _rerender:`, error);
|
|
1432
1988
|
this.renderError(error);
|
|
1433
1989
|
this._isRendering = false;
|
|
1434
1990
|
}
|
|
@@ -1550,6 +2106,10 @@ To fix this, please:
|
|
|
1550
2106
|
See: https://github.com/wsxjs/wsxjs#setup for more details.`;
|
|
1551
2107
|
}
|
|
1552
2108
|
function state(targetOrContext, propertyKey) {
|
|
2109
|
+
const globalProcess = typeof globalThis !== "undefined" ? globalThis.process : void 0;
|
|
2110
|
+
if (globalProcess?.env?.NODE_ENV === "test") {
|
|
2111
|
+
return;
|
|
2112
|
+
}
|
|
1553
2113
|
let propertyName = "unknown";
|
|
1554
2114
|
const propertyKeyIsObject = typeof propertyKey === "object" && propertyKey !== null;
|
|
1555
2115
|
const targetIsObject = typeof targetOrContext === "object" && targetOrContext !== null;
|