what-core 0.6.0 → 0.6.1
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/index.js +114 -50
- package/dist/index.js.map +2 -2
- package/dist/index.min.js +6 -6
- package/dist/index.min.js.map +3 -3
- package/dist/render.js +97 -49
- package/dist/render.js.map +2 -2
- package/dist/render.min.js +1 -1
- package/dist/render.min.js.map +3 -3
- package/dist/testing.js +100 -47
- package/dist/testing.js.map +2 -2
- package/dist/testing.min.js +1 -1
- package/dist/testing.min.js.map +3 -3
- package/package.json +1 -1
- package/src/dom.js +60 -20
- package/src/reactive.js +78 -40
- package/src/render.js +17 -0
package/dist/testing.js
CHANGED
|
@@ -285,43 +285,66 @@ function scheduleMicrotask() {
|
|
|
285
285
|
});
|
|
286
286
|
}
|
|
287
287
|
}
|
|
288
|
+
var isFlushing = false;
|
|
288
289
|
function flush() {
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
batch2
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
const
|
|
302
|
-
|
|
303
|
-
if (!e.
|
|
304
|
-
|
|
290
|
+
if (isFlushing) return;
|
|
291
|
+
isFlushing = true;
|
|
292
|
+
try {
|
|
293
|
+
let iterations = 0;
|
|
294
|
+
while (pendingEffects.length > 0 && iterations < 25) {
|
|
295
|
+
const batch2 = pendingEffects;
|
|
296
|
+
pendingEffects = [];
|
|
297
|
+
if (batch2.length > 1 && pendingNeedSort) {
|
|
298
|
+
batch2.sort((a, b) => a._level - b._level);
|
|
299
|
+
}
|
|
300
|
+
pendingNeedSort = false;
|
|
301
|
+
for (let i = 0; i < batch2.length; i++) {
|
|
302
|
+
const e = batch2[i];
|
|
303
|
+
e._pending = false;
|
|
304
|
+
if (!e.disposed && !e._onNotify) {
|
|
305
|
+
const prevDepsLen = e.deps.length;
|
|
306
|
+
_runEffect(e);
|
|
307
|
+
if (!e._computed && e.deps.length !== prevDepsLen) {
|
|
308
|
+
_updateLevel(e);
|
|
309
|
+
}
|
|
305
310
|
}
|
|
306
311
|
}
|
|
312
|
+
iterations++;
|
|
313
|
+
}
|
|
314
|
+
if (iterations >= 25) {
|
|
315
|
+
for (let i = 0; i < pendingEffects.length; i++) pendingEffects[i]._pending = false;
|
|
316
|
+
pendingEffects.length = 0;
|
|
317
|
+
if (__DEV__) {
|
|
318
|
+
const remaining = pendingEffects.slice(0, 3);
|
|
319
|
+
const effectNames = remaining.map((e) => e.fn?.name || e.fn?.toString().slice(0, 60) || "(anonymous)");
|
|
320
|
+
console.warn(
|
|
321
|
+
`[what] Possible infinite effect loop detected (25 iterations). Likely cause: an effect writes to a signal it also reads, creating a cycle. Use untrack() to read signals without subscribing. Looping effects: ${effectNames.join(", ")}`
|
|
322
|
+
);
|
|
323
|
+
} else {
|
|
324
|
+
console.warn("[what] Possible infinite effect loop detected");
|
|
325
|
+
}
|
|
307
326
|
}
|
|
308
|
-
|
|
327
|
+
} finally {
|
|
328
|
+
isFlushing = false;
|
|
309
329
|
}
|
|
310
|
-
|
|
330
|
+
}
|
|
331
|
+
function flushSync() {
|
|
332
|
+
if (isFlushing) {
|
|
311
333
|
if (__DEV__) {
|
|
312
|
-
const remaining = pendingEffects.slice(0, 3);
|
|
313
|
-
const effectNames = remaining.map((e) => e.fn?.name || e.fn?.toString().slice(0, 60) || "(anonymous)");
|
|
314
334
|
console.warn(
|
|
315
|
-
|
|
335
|
+
"[what] flushSync() called during an active flush (e.g., inside a component render or effect). This is a no-op to prevent infinite loops. Move flushSync() to an event handler or onMount callback."
|
|
316
336
|
);
|
|
317
|
-
} else {
|
|
318
|
-
console.warn("[what] Possible infinite effect loop detected");
|
|
319
337
|
}
|
|
320
|
-
|
|
321
|
-
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
if (currentEffect) {
|
|
341
|
+
if (__DEV__) {
|
|
342
|
+
console.warn(
|
|
343
|
+
"[what] flushSync() called during effect execution. This is a no-op to prevent infinite loops. Move flushSync() to an event handler or onMount callback."
|
|
344
|
+
);
|
|
345
|
+
}
|
|
346
|
+
return;
|
|
322
347
|
}
|
|
323
|
-
}
|
|
324
|
-
function flushSync() {
|
|
325
348
|
microtaskScheduled = false;
|
|
326
349
|
flush();
|
|
327
350
|
}
|
|
@@ -762,8 +785,8 @@ function createComponent(vnode, parent, isSvg) {
|
|
|
762
785
|
function createErrorBoundary(vnode, parent) {
|
|
763
786
|
const { errorState, handleError, fallback, reset } = vnode.props;
|
|
764
787
|
const children = vnode.children;
|
|
765
|
-
const
|
|
766
|
-
|
|
788
|
+
const startComment = document.createComment("eb:start");
|
|
789
|
+
const endComment = document.createComment("eb:end");
|
|
767
790
|
const boundaryCtx = {
|
|
768
791
|
hooks: [],
|
|
769
792
|
hookIndex: 0,
|
|
@@ -772,15 +795,24 @@ function createErrorBoundary(vnode, parent) {
|
|
|
772
795
|
mounted: false,
|
|
773
796
|
disposed: false,
|
|
774
797
|
_parentCtx: componentStack[componentStack.length - 1] || null,
|
|
775
|
-
_errorBoundary: handleError
|
|
798
|
+
_errorBoundary: handleError,
|
|
799
|
+
_startComment: startComment,
|
|
800
|
+
_endComment: endComment
|
|
776
801
|
};
|
|
777
|
-
|
|
802
|
+
_commentCtxMap.set(startComment, boundaryCtx);
|
|
803
|
+
const container2 = document.createDocumentFragment();
|
|
804
|
+
container2._componentCtx = boundaryCtx;
|
|
805
|
+
container2.appendChild(startComment);
|
|
806
|
+
container2.appendChild(endComment);
|
|
778
807
|
const dispose = effect(() => {
|
|
779
808
|
const error = errorState();
|
|
780
809
|
componentStack.push(boundaryCtx);
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
810
|
+
if (startComment.parentNode) {
|
|
811
|
+
while (startComment.nextSibling && startComment.nextSibling !== endComment) {
|
|
812
|
+
const old = startComment.nextSibling;
|
|
813
|
+
disposeTree(old);
|
|
814
|
+
old.parentNode.removeChild(old);
|
|
815
|
+
}
|
|
784
816
|
}
|
|
785
817
|
let vnodes;
|
|
786
818
|
if (error) {
|
|
@@ -790,19 +822,25 @@ function createErrorBoundary(vnode, parent) {
|
|
|
790
822
|
}
|
|
791
823
|
vnodes = Array.isArray(vnodes) ? vnodes : [vnodes];
|
|
792
824
|
for (const v of vnodes) {
|
|
793
|
-
const node = createDOM(v,
|
|
794
|
-
if (node)
|
|
825
|
+
const node = createDOM(v, parent);
|
|
826
|
+
if (node) {
|
|
827
|
+
if (endComment.parentNode) {
|
|
828
|
+
endComment.parentNode.insertBefore(node, endComment);
|
|
829
|
+
} else {
|
|
830
|
+
container2.insertBefore(node, endComment);
|
|
831
|
+
}
|
|
832
|
+
}
|
|
795
833
|
}
|
|
796
834
|
componentStack.pop();
|
|
797
835
|
});
|
|
798
836
|
boundaryCtx.effects.push(dispose);
|
|
799
|
-
return
|
|
837
|
+
return container2;
|
|
800
838
|
}
|
|
801
839
|
function createSuspenseBoundary(vnode, parent) {
|
|
802
840
|
const { boundary, fallback, loading } = vnode.props;
|
|
803
841
|
const children = vnode.children;
|
|
804
|
-
const
|
|
805
|
-
|
|
842
|
+
const startComment = document.createComment("sb:start");
|
|
843
|
+
const endComment = document.createComment("sb:end");
|
|
806
844
|
const boundaryCtx = {
|
|
807
845
|
hooks: [],
|
|
808
846
|
hookIndex: 0,
|
|
@@ -810,26 +848,41 @@ function createSuspenseBoundary(vnode, parent) {
|
|
|
810
848
|
cleanups: [],
|
|
811
849
|
mounted: false,
|
|
812
850
|
disposed: false,
|
|
813
|
-
_parentCtx: componentStack[componentStack.length - 1] || null
|
|
851
|
+
_parentCtx: componentStack[componentStack.length - 1] || null,
|
|
852
|
+
_startComment: startComment,
|
|
853
|
+
_endComment: endComment
|
|
814
854
|
};
|
|
815
|
-
|
|
855
|
+
_commentCtxMap.set(startComment, boundaryCtx);
|
|
856
|
+
const container2 = document.createDocumentFragment();
|
|
857
|
+
container2._componentCtx = boundaryCtx;
|
|
858
|
+
container2.appendChild(startComment);
|
|
859
|
+
container2.appendChild(endComment);
|
|
816
860
|
const dispose = effect(() => {
|
|
817
861
|
const isLoading = loading();
|
|
818
862
|
const vnodes = isLoading ? [fallback] : children;
|
|
819
863
|
const normalized = Array.isArray(vnodes) ? vnodes : [vnodes];
|
|
820
864
|
componentStack.push(boundaryCtx);
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
865
|
+
if (startComment.parentNode) {
|
|
866
|
+
while (startComment.nextSibling && startComment.nextSibling !== endComment) {
|
|
867
|
+
const old = startComment.nextSibling;
|
|
868
|
+
disposeTree(old);
|
|
869
|
+
old.parentNode.removeChild(old);
|
|
870
|
+
}
|
|
824
871
|
}
|
|
825
872
|
for (const v of normalized) {
|
|
826
|
-
const node = createDOM(v,
|
|
827
|
-
if (node)
|
|
873
|
+
const node = createDOM(v, parent);
|
|
874
|
+
if (node) {
|
|
875
|
+
if (endComment.parentNode) {
|
|
876
|
+
endComment.parentNode.insertBefore(node, endComment);
|
|
877
|
+
} else {
|
|
878
|
+
container2.insertBefore(node, endComment);
|
|
879
|
+
}
|
|
880
|
+
}
|
|
828
881
|
}
|
|
829
882
|
componentStack.pop();
|
|
830
883
|
});
|
|
831
884
|
boundaryCtx.effects.push(dispose);
|
|
832
|
-
return
|
|
885
|
+
return container2;
|
|
833
886
|
}
|
|
834
887
|
function createPortalDOM(vnode, parent) {
|
|
835
888
|
const { container: container2 } = vnode.props;
|