veles 1.1.1 → 1.1.3
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.
|
@@ -108,11 +108,20 @@ function executeComponent({ element, props }) {
|
|
|
108
108
|
}
|
|
109
109
|
//#endregion
|
|
110
110
|
//#region src/create-element/parse-children.ts
|
|
111
|
+
function flattenChildren(children) {
|
|
112
|
+
const flattenedChildren = [];
|
|
113
|
+
function append(child) {
|
|
114
|
+
if (Array.isArray(child)) child.forEach(append);
|
|
115
|
+
else flattenedChildren.push(child);
|
|
116
|
+
}
|
|
117
|
+
append(children);
|
|
118
|
+
return flattenedChildren;
|
|
119
|
+
}
|
|
111
120
|
function parseChildren({ children, htmlElement, velesNode, portal }) {
|
|
112
121
|
const childComponents = [];
|
|
113
122
|
if (children === void 0 || children === null) return childComponents;
|
|
114
123
|
let lastInsertedNode = null;
|
|
115
|
-
(
|
|
124
|
+
flattenChildren(children).forEach((childComponent) => {
|
|
116
125
|
if (typeof childComponent === "string") {
|
|
117
126
|
const textNode = createTextElement(childComponent);
|
|
118
127
|
htmlElement.append(textNode.html);
|
|
@@ -108,11 +108,20 @@ function executeComponent({ element, props }) {
|
|
|
108
108
|
}
|
|
109
109
|
//#endregion
|
|
110
110
|
//#region src/create-element/parse-children.ts
|
|
111
|
+
function flattenChildren(children) {
|
|
112
|
+
const flattenedChildren = [];
|
|
113
|
+
function append(child) {
|
|
114
|
+
if (Array.isArray(child)) child.forEach(append);
|
|
115
|
+
else flattenedChildren.push(child);
|
|
116
|
+
}
|
|
117
|
+
append(children);
|
|
118
|
+
return flattenedChildren;
|
|
119
|
+
}
|
|
111
120
|
function parseChildren({ children, htmlElement, velesNode, portal }) {
|
|
112
121
|
const childComponents = [];
|
|
113
122
|
if (children === void 0 || children === null) return childComponents;
|
|
114
123
|
let lastInsertedNode = null;
|
|
115
|
-
(
|
|
124
|
+
flattenChildren(children).forEach((childComponent) => {
|
|
116
125
|
if (typeof childComponent === "string") {
|
|
117
126
|
const textNode = createTextElement(childComponent);
|
|
118
127
|
htmlElement.append(textNode.html);
|
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require__utils = require("./_utils-
|
|
2
|
+
const require__utils = require("./_utils-DbrPydEE.cjs");
|
|
3
3
|
//#region src/attach-component.ts
|
|
4
4
|
/**
|
|
5
5
|
* Attach Veles component tree to a regular HTML node.
|
|
@@ -370,6 +370,113 @@ function triggerUpdates({ value, createState, trackers, get }) {
|
|
|
370
370
|
});
|
|
371
371
|
}
|
|
372
372
|
//#endregion
|
|
373
|
+
//#region src/create-state/min-heap.ts
|
|
374
|
+
/**
|
|
375
|
+
* A stable min-heap. Values with the same priority are returned in
|
|
376
|
+
* insertion order.
|
|
377
|
+
*/
|
|
378
|
+
var MinHeap = class {
|
|
379
|
+
constructor(compareValues) {
|
|
380
|
+
this._entries = [];
|
|
381
|
+
this._insertionOrder = 0;
|
|
382
|
+
this._compareValues = compareValues;
|
|
383
|
+
}
|
|
384
|
+
get size() {
|
|
385
|
+
return this._entries.length;
|
|
386
|
+
}
|
|
387
|
+
push(value) {
|
|
388
|
+
const entry = {
|
|
389
|
+
value,
|
|
390
|
+
insertionOrder: this._insertionOrder++
|
|
391
|
+
};
|
|
392
|
+
let index = this._entries.length;
|
|
393
|
+
this._entries.push(entry);
|
|
394
|
+
while (index > 0) {
|
|
395
|
+
const parentIndex = Math.floor((index - 1) / 2);
|
|
396
|
+
const parentEntry = this._entries[parentIndex];
|
|
397
|
+
if (this.compareEntries(parentEntry, entry) <= 0) break;
|
|
398
|
+
this._entries[index] = parentEntry;
|
|
399
|
+
index = parentIndex;
|
|
400
|
+
}
|
|
401
|
+
this._entries[index] = entry;
|
|
402
|
+
}
|
|
403
|
+
pop() {
|
|
404
|
+
const firstEntry = this._entries[0];
|
|
405
|
+
const lastEntry = this._entries.pop();
|
|
406
|
+
if (!firstEntry || !lastEntry) return void 0;
|
|
407
|
+
if (this._entries.length === 0) return firstEntry.value;
|
|
408
|
+
let index = 0;
|
|
409
|
+
while (true) {
|
|
410
|
+
const leftChildIndex = index * 2 + 1;
|
|
411
|
+
const rightChildIndex = leftChildIndex + 1;
|
|
412
|
+
let smallestIndex = index;
|
|
413
|
+
if (leftChildIndex < this._entries.length && this.compareEntries(this._entries[leftChildIndex], lastEntry) < 0) smallestIndex = leftChildIndex;
|
|
414
|
+
if (rightChildIndex < this._entries.length && this.compareEntries(this._entries[rightChildIndex], smallestIndex === index ? lastEntry : this._entries[leftChildIndex]) < 0) smallestIndex = rightChildIndex;
|
|
415
|
+
if (smallestIndex === index) break;
|
|
416
|
+
this._entries[index] = this._entries[smallestIndex];
|
|
417
|
+
index = smallestIndex;
|
|
418
|
+
}
|
|
419
|
+
this._entries[index] = lastEntry;
|
|
420
|
+
return firstEntry.value;
|
|
421
|
+
}
|
|
422
|
+
compareEntries(entry1, entry2) {
|
|
423
|
+
const valueComparison = this._compareValues(entry1.value, entry2.value);
|
|
424
|
+
return valueComparison === 0 ? entry1.insertionOrder - entry2.insertionOrder : valueComparison;
|
|
425
|
+
}
|
|
426
|
+
};
|
|
427
|
+
//#endregion
|
|
428
|
+
//#region src/create-state/state-scheduler.ts
|
|
429
|
+
/**
|
|
430
|
+
* Coordinates notifications produced by one synchronous state transaction.
|
|
431
|
+
*
|
|
432
|
+
* A subscriber can synchronously update another state. That nested update adds
|
|
433
|
+
* its notifications to this same scheduler, allowing an older notification for
|
|
434
|
+
* the same state to be replaced before it is delivered.
|
|
435
|
+
*/
|
|
436
|
+
var StateScheduler = class {
|
|
437
|
+
constructor() {
|
|
438
|
+
this._notifications = new MinHeap((notification1, notification2) => notification1.rank - notification2.rank);
|
|
439
|
+
this._notificationsByKey = /* @__PURE__ */ new Map();
|
|
440
|
+
}
|
|
441
|
+
scheduleNotification(notification) {
|
|
442
|
+
const existingNotification = this._notificationsByKey.get(notification.key);
|
|
443
|
+
if (existingNotification) {
|
|
444
|
+
existingNotification.value = notification.value;
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
this._notificationsByKey.set(notification.key, notification);
|
|
448
|
+
this._notifications.push(notification);
|
|
449
|
+
}
|
|
450
|
+
deliverNotifications() {
|
|
451
|
+
while (this._notifications.size > 0) {
|
|
452
|
+
const notification = this._notifications.pop();
|
|
453
|
+
if (this._notificationsByKey.get(notification.key) !== notification) continue;
|
|
454
|
+
this._notificationsByKey.delete(notification.key);
|
|
455
|
+
notification.notify(notification.value, notification.previousValue);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
};
|
|
459
|
+
let activeScheduler;
|
|
460
|
+
/**
|
|
461
|
+
* Top-level state updates own the scheduler and synchronously drain it. Updates
|
|
462
|
+
* made by subscribers reuse the active scheduler, so they cannot deliver a
|
|
463
|
+
* nested notification batch ahead of notifications already waiting to run.
|
|
464
|
+
*/
|
|
465
|
+
function runWithStateScheduler(runUpdate) {
|
|
466
|
+
if (activeScheduler) {
|
|
467
|
+
runUpdate(activeScheduler);
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
const scheduler = new StateScheduler();
|
|
471
|
+
activeScheduler = scheduler;
|
|
472
|
+
try {
|
|
473
|
+
runUpdate(scheduler);
|
|
474
|
+
scheduler.deliverNotifications();
|
|
475
|
+
} finally {
|
|
476
|
+
activeScheduler = void 0;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
//#endregion
|
|
373
480
|
//#region src/create-state/state-core.ts
|
|
374
481
|
const emptyValue = Symbol("veles-state-core-empty");
|
|
375
482
|
const defaultEquality = (value1, value2) => value1 === value2;
|
|
@@ -380,8 +487,10 @@ var StateCore = class StateCore {
|
|
|
380
487
|
this._dirty = false;
|
|
381
488
|
this._children = /* @__PURE__ */ new Set();
|
|
382
489
|
this._value = initialValue;
|
|
383
|
-
|
|
490
|
+
const parents = options.parents || [];
|
|
491
|
+
this._parents = new Set(parents);
|
|
384
492
|
this._compute = options.compute;
|
|
493
|
+
this._rank = parents.reduce((rank, parent) => Math.max(rank, parent._rank + 1), 0);
|
|
385
494
|
this._dirty = Boolean(options.dirty);
|
|
386
495
|
this._equality = options.equality || defaultEquality;
|
|
387
496
|
}
|
|
@@ -400,14 +509,16 @@ var StateCore = class StateCore {
|
|
|
400
509
|
}
|
|
401
510
|
set(newValue) {
|
|
402
511
|
if (this._equality(this._value, newValue)) return;
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
child
|
|
512
|
+
runWithStateScheduler((scheduler) => {
|
|
513
|
+
const prevValue = this._value;
|
|
514
|
+
this._prevValue = prevValue;
|
|
515
|
+
this._value = newValue;
|
|
516
|
+
this.scheduleNotification(scheduler, newValue, prevValue);
|
|
517
|
+
this._children.forEach((child) => {
|
|
518
|
+
child._dirty = true;
|
|
519
|
+
});
|
|
520
|
+
this.flush(scheduler);
|
|
409
521
|
});
|
|
410
|
-
this.flush();
|
|
411
522
|
}
|
|
412
523
|
update(fn) {
|
|
413
524
|
const newValue = fn(this._value);
|
|
@@ -494,37 +605,62 @@ var StateCore = class StateCore {
|
|
|
494
605
|
this._dirty = false;
|
|
495
606
|
return { changed };
|
|
496
607
|
}
|
|
497
|
-
flush() {
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
608
|
+
flush(scheduler) {
|
|
609
|
+
/**
|
|
610
|
+
* We utilize a min-heap to ensure that we don't trigger notifications
|
|
611
|
+
* before all the previous necessary work is done. Otherwise it can
|
|
612
|
+
* happen too early, and we'd need to recursively check that every parent
|
|
613
|
+
* is not dirty and schedule it again.
|
|
614
|
+
*
|
|
615
|
+
* Here we achieve this by assinging a rank to each core state, which is
|
|
616
|
+
* determined by the highest rank of any of the parent + 1.
|
|
617
|
+
*
|
|
618
|
+
* After that, we process them at the same rank, ensuring that "short" branches
|
|
619
|
+
* are not executed before all their parents are done with their recomputation.
|
|
620
|
+
*/
|
|
621
|
+
const queue = new MinHeap((node1, node2) => node1._rank - node2._rank);
|
|
622
|
+
const queued = /* @__PURE__ */ new Set();
|
|
623
|
+
const enqueue = (node) => {
|
|
624
|
+
if (queued.has(node)) return;
|
|
625
|
+
queue.push(node);
|
|
626
|
+
queued.add(node);
|
|
627
|
+
};
|
|
628
|
+
this._children.forEach(enqueue);
|
|
629
|
+
while (queue.size > 0) {
|
|
630
|
+
const child = queue.pop();
|
|
502
631
|
queued.delete(child);
|
|
503
632
|
if (!child._dirty) continue;
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
633
|
+
let shouldRescheduleChild = false;
|
|
634
|
+
child._parents.forEach((parentNode) => {
|
|
635
|
+
if (parentNode._dirty) {
|
|
636
|
+
enqueue(parentNode);
|
|
637
|
+
shouldRescheduleChild = true;
|
|
638
|
+
}
|
|
639
|
+
});
|
|
640
|
+
if (shouldRescheduleChild) {
|
|
641
|
+
enqueue(child);
|
|
507
642
|
continue;
|
|
508
643
|
}
|
|
509
644
|
const { changed } = child.recompute();
|
|
510
645
|
const value = child._value;
|
|
511
646
|
if (!changed) continue;
|
|
512
|
-
child.
|
|
647
|
+
child.scheduleNotification(scheduler, value, child._prevValue);
|
|
513
648
|
child._children.forEach((grandchild) => {
|
|
514
649
|
grandchild._dirty = true;
|
|
515
|
-
|
|
516
|
-
queue.push(grandchild);
|
|
517
|
-
queued.add(grandchild);
|
|
518
|
-
}
|
|
650
|
+
enqueue(grandchild);
|
|
519
651
|
});
|
|
520
652
|
}
|
|
521
653
|
}
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
654
|
+
scheduleNotification(scheduler, value, previousValue) {
|
|
655
|
+
scheduler.scheduleNotification({
|
|
656
|
+
key: this,
|
|
657
|
+
rank: this._rank,
|
|
658
|
+
value,
|
|
659
|
+
previousValue,
|
|
660
|
+
notify: (notificationValue, notificationPreviousValue) => {
|
|
661
|
+
this.notifySubscribers(notificationValue, notificationPreviousValue);
|
|
662
|
+
}
|
|
526
663
|
});
|
|
527
|
-
return hasDirtyParent;
|
|
528
664
|
}
|
|
529
665
|
notifySubscribers(value, prevValue) {
|
|
530
666
|
if (value === emptyValue) return;
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _ as onMount, a as identity, c as addPublicContext, d as popPublicContext, f as Fragment, g as hasCurrentLifecycleContext, h as createTextElement, i as getMountedNodeExecutedVersion, l as createContext, m as assignDomAttribute, n as callUnmountHandlers, o as renderTree, p as createElement, r as getExecutedComponentVelesNode, s as unique, t as callMountHandlers, u as getCurrentContext, v as onUnmount } from "./_utils-
|
|
1
|
+
import { _ as onMount, a as identity, c as addPublicContext, d as popPublicContext, f as Fragment, g as hasCurrentLifecycleContext, h as createTextElement, i as getMountedNodeExecutedVersion, l as createContext, m as assignDomAttribute, n as callUnmountHandlers, o as renderTree, p as createElement, r as getExecutedComponentVelesNode, s as unique, t as callMountHandlers, u as getCurrentContext, v as onUnmount } from "./_utils-BnAXelPu.js";
|
|
2
2
|
//#region src/attach-component.ts
|
|
3
3
|
/**
|
|
4
4
|
* Attach Veles component tree to a regular HTML node.
|
|
@@ -369,6 +369,113 @@ function triggerUpdates({ value, createState, trackers, get }) {
|
|
|
369
369
|
});
|
|
370
370
|
}
|
|
371
371
|
//#endregion
|
|
372
|
+
//#region src/create-state/min-heap.ts
|
|
373
|
+
/**
|
|
374
|
+
* A stable min-heap. Values with the same priority are returned in
|
|
375
|
+
* insertion order.
|
|
376
|
+
*/
|
|
377
|
+
var MinHeap = class {
|
|
378
|
+
constructor(compareValues) {
|
|
379
|
+
this._entries = [];
|
|
380
|
+
this._insertionOrder = 0;
|
|
381
|
+
this._compareValues = compareValues;
|
|
382
|
+
}
|
|
383
|
+
get size() {
|
|
384
|
+
return this._entries.length;
|
|
385
|
+
}
|
|
386
|
+
push(value) {
|
|
387
|
+
const entry = {
|
|
388
|
+
value,
|
|
389
|
+
insertionOrder: this._insertionOrder++
|
|
390
|
+
};
|
|
391
|
+
let index = this._entries.length;
|
|
392
|
+
this._entries.push(entry);
|
|
393
|
+
while (index > 0) {
|
|
394
|
+
const parentIndex = Math.floor((index - 1) / 2);
|
|
395
|
+
const parentEntry = this._entries[parentIndex];
|
|
396
|
+
if (this.compareEntries(parentEntry, entry) <= 0) break;
|
|
397
|
+
this._entries[index] = parentEntry;
|
|
398
|
+
index = parentIndex;
|
|
399
|
+
}
|
|
400
|
+
this._entries[index] = entry;
|
|
401
|
+
}
|
|
402
|
+
pop() {
|
|
403
|
+
const firstEntry = this._entries[0];
|
|
404
|
+
const lastEntry = this._entries.pop();
|
|
405
|
+
if (!firstEntry || !lastEntry) return void 0;
|
|
406
|
+
if (this._entries.length === 0) return firstEntry.value;
|
|
407
|
+
let index = 0;
|
|
408
|
+
while (true) {
|
|
409
|
+
const leftChildIndex = index * 2 + 1;
|
|
410
|
+
const rightChildIndex = leftChildIndex + 1;
|
|
411
|
+
let smallestIndex = index;
|
|
412
|
+
if (leftChildIndex < this._entries.length && this.compareEntries(this._entries[leftChildIndex], lastEntry) < 0) smallestIndex = leftChildIndex;
|
|
413
|
+
if (rightChildIndex < this._entries.length && this.compareEntries(this._entries[rightChildIndex], smallestIndex === index ? lastEntry : this._entries[leftChildIndex]) < 0) smallestIndex = rightChildIndex;
|
|
414
|
+
if (smallestIndex === index) break;
|
|
415
|
+
this._entries[index] = this._entries[smallestIndex];
|
|
416
|
+
index = smallestIndex;
|
|
417
|
+
}
|
|
418
|
+
this._entries[index] = lastEntry;
|
|
419
|
+
return firstEntry.value;
|
|
420
|
+
}
|
|
421
|
+
compareEntries(entry1, entry2) {
|
|
422
|
+
const valueComparison = this._compareValues(entry1.value, entry2.value);
|
|
423
|
+
return valueComparison === 0 ? entry1.insertionOrder - entry2.insertionOrder : valueComparison;
|
|
424
|
+
}
|
|
425
|
+
};
|
|
426
|
+
//#endregion
|
|
427
|
+
//#region src/create-state/state-scheduler.ts
|
|
428
|
+
/**
|
|
429
|
+
* Coordinates notifications produced by one synchronous state transaction.
|
|
430
|
+
*
|
|
431
|
+
* A subscriber can synchronously update another state. That nested update adds
|
|
432
|
+
* its notifications to this same scheduler, allowing an older notification for
|
|
433
|
+
* the same state to be replaced before it is delivered.
|
|
434
|
+
*/
|
|
435
|
+
var StateScheduler = class {
|
|
436
|
+
constructor() {
|
|
437
|
+
this._notifications = new MinHeap((notification1, notification2) => notification1.rank - notification2.rank);
|
|
438
|
+
this._notificationsByKey = /* @__PURE__ */ new Map();
|
|
439
|
+
}
|
|
440
|
+
scheduleNotification(notification) {
|
|
441
|
+
const existingNotification = this._notificationsByKey.get(notification.key);
|
|
442
|
+
if (existingNotification) {
|
|
443
|
+
existingNotification.value = notification.value;
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
this._notificationsByKey.set(notification.key, notification);
|
|
447
|
+
this._notifications.push(notification);
|
|
448
|
+
}
|
|
449
|
+
deliverNotifications() {
|
|
450
|
+
while (this._notifications.size > 0) {
|
|
451
|
+
const notification = this._notifications.pop();
|
|
452
|
+
if (this._notificationsByKey.get(notification.key) !== notification) continue;
|
|
453
|
+
this._notificationsByKey.delete(notification.key);
|
|
454
|
+
notification.notify(notification.value, notification.previousValue);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
};
|
|
458
|
+
let activeScheduler;
|
|
459
|
+
/**
|
|
460
|
+
* Top-level state updates own the scheduler and synchronously drain it. Updates
|
|
461
|
+
* made by subscribers reuse the active scheduler, so they cannot deliver a
|
|
462
|
+
* nested notification batch ahead of notifications already waiting to run.
|
|
463
|
+
*/
|
|
464
|
+
function runWithStateScheduler(runUpdate) {
|
|
465
|
+
if (activeScheduler) {
|
|
466
|
+
runUpdate(activeScheduler);
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
const scheduler = new StateScheduler();
|
|
470
|
+
activeScheduler = scheduler;
|
|
471
|
+
try {
|
|
472
|
+
runUpdate(scheduler);
|
|
473
|
+
scheduler.deliverNotifications();
|
|
474
|
+
} finally {
|
|
475
|
+
activeScheduler = void 0;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
//#endregion
|
|
372
479
|
//#region src/create-state/state-core.ts
|
|
373
480
|
const emptyValue = Symbol("veles-state-core-empty");
|
|
374
481
|
const defaultEquality = (value1, value2) => value1 === value2;
|
|
@@ -379,8 +486,10 @@ var StateCore = class StateCore {
|
|
|
379
486
|
this._dirty = false;
|
|
380
487
|
this._children = /* @__PURE__ */ new Set();
|
|
381
488
|
this._value = initialValue;
|
|
382
|
-
|
|
489
|
+
const parents = options.parents || [];
|
|
490
|
+
this._parents = new Set(parents);
|
|
383
491
|
this._compute = options.compute;
|
|
492
|
+
this._rank = parents.reduce((rank, parent) => Math.max(rank, parent._rank + 1), 0);
|
|
384
493
|
this._dirty = Boolean(options.dirty);
|
|
385
494
|
this._equality = options.equality || defaultEquality;
|
|
386
495
|
}
|
|
@@ -399,14 +508,16 @@ var StateCore = class StateCore {
|
|
|
399
508
|
}
|
|
400
509
|
set(newValue) {
|
|
401
510
|
if (this._equality(this._value, newValue)) return;
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
child
|
|
511
|
+
runWithStateScheduler((scheduler) => {
|
|
512
|
+
const prevValue = this._value;
|
|
513
|
+
this._prevValue = prevValue;
|
|
514
|
+
this._value = newValue;
|
|
515
|
+
this.scheduleNotification(scheduler, newValue, prevValue);
|
|
516
|
+
this._children.forEach((child) => {
|
|
517
|
+
child._dirty = true;
|
|
518
|
+
});
|
|
519
|
+
this.flush(scheduler);
|
|
408
520
|
});
|
|
409
|
-
this.flush();
|
|
410
521
|
}
|
|
411
522
|
update(fn) {
|
|
412
523
|
const newValue = fn(this._value);
|
|
@@ -493,37 +604,62 @@ var StateCore = class StateCore {
|
|
|
493
604
|
this._dirty = false;
|
|
494
605
|
return { changed };
|
|
495
606
|
}
|
|
496
|
-
flush() {
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
607
|
+
flush(scheduler) {
|
|
608
|
+
/**
|
|
609
|
+
* We utilize a min-heap to ensure that we don't trigger notifications
|
|
610
|
+
* before all the previous necessary work is done. Otherwise it can
|
|
611
|
+
* happen too early, and we'd need to recursively check that every parent
|
|
612
|
+
* is not dirty and schedule it again.
|
|
613
|
+
*
|
|
614
|
+
* Here we achieve this by assinging a rank to each core state, which is
|
|
615
|
+
* determined by the highest rank of any of the parent + 1.
|
|
616
|
+
*
|
|
617
|
+
* After that, we process them at the same rank, ensuring that "short" branches
|
|
618
|
+
* are not executed before all their parents are done with their recomputation.
|
|
619
|
+
*/
|
|
620
|
+
const queue = new MinHeap((node1, node2) => node1._rank - node2._rank);
|
|
621
|
+
const queued = /* @__PURE__ */ new Set();
|
|
622
|
+
const enqueue = (node) => {
|
|
623
|
+
if (queued.has(node)) return;
|
|
624
|
+
queue.push(node);
|
|
625
|
+
queued.add(node);
|
|
626
|
+
};
|
|
627
|
+
this._children.forEach(enqueue);
|
|
628
|
+
while (queue.size > 0) {
|
|
629
|
+
const child = queue.pop();
|
|
501
630
|
queued.delete(child);
|
|
502
631
|
if (!child._dirty) continue;
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
632
|
+
let shouldRescheduleChild = false;
|
|
633
|
+
child._parents.forEach((parentNode) => {
|
|
634
|
+
if (parentNode._dirty) {
|
|
635
|
+
enqueue(parentNode);
|
|
636
|
+
shouldRescheduleChild = true;
|
|
637
|
+
}
|
|
638
|
+
});
|
|
639
|
+
if (shouldRescheduleChild) {
|
|
640
|
+
enqueue(child);
|
|
506
641
|
continue;
|
|
507
642
|
}
|
|
508
643
|
const { changed } = child.recompute();
|
|
509
644
|
const value = child._value;
|
|
510
645
|
if (!changed) continue;
|
|
511
|
-
child.
|
|
646
|
+
child.scheduleNotification(scheduler, value, child._prevValue);
|
|
512
647
|
child._children.forEach((grandchild) => {
|
|
513
648
|
grandchild._dirty = true;
|
|
514
|
-
|
|
515
|
-
queue.push(grandchild);
|
|
516
|
-
queued.add(grandchild);
|
|
517
|
-
}
|
|
649
|
+
enqueue(grandchild);
|
|
518
650
|
});
|
|
519
651
|
}
|
|
520
652
|
}
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
653
|
+
scheduleNotification(scheduler, value, previousValue) {
|
|
654
|
+
scheduler.scheduleNotification({
|
|
655
|
+
key: this,
|
|
656
|
+
rank: this._rank,
|
|
657
|
+
value,
|
|
658
|
+
previousValue,
|
|
659
|
+
notify: (notificationValue, notificationPreviousValue) => {
|
|
660
|
+
this.notifySubscribers(notificationValue, notificationPreviousValue);
|
|
661
|
+
}
|
|
525
662
|
});
|
|
526
|
-
return hasDirtyParent;
|
|
527
663
|
}
|
|
528
664
|
notifySubscribers(value, prevValue) {
|
|
529
665
|
if (value === emptyValue) return;
|
package/dist/jsx-runtime.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require__utils = require("./_utils-
|
|
2
|
+
const require__utils = require("./_utils-DbrPydEE.cjs");
|
|
3
3
|
exports.Fragment = require__utils.Fragment;
|
|
4
4
|
exports.jsx = require__utils.createElement;
|
|
5
5
|
exports.jsxDEV = require__utils.createElement;
|
package/dist/jsx-runtime.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { f as Fragment, p as createElement } from "./_utils-
|
|
1
|
+
import { f as Fragment, p as createElement } from "./_utils-BnAXelPu.js";
|
|
2
2
|
export { Fragment, createElement as jsx, createElement as jsxDEV, createElement as jsxs };
|