@farm.js/react 0.1.0-beta.10 → 0.1.0-beta.11
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/README.md +20 -8
- package/dist/compiler-runtime.cjs +34 -37
- package/dist/compiler-runtime.cjs.map +1 -1
- package/dist/compiler-runtime.mjs +34 -37
- package/dist/compiler-runtime.mjs.map +1 -1
- package/dist/vite.cjs +19 -8
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.mjs +19 -8
- package/dist/vite.mjs.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -496,7 +496,11 @@ through one document fragment. It then removes only the replaced window. When th
|
|
|
496
496
|
has the same length and the same keys in the same order, Farm prepares every binding read and
|
|
497
497
|
changed DOM target across the complete window first, patches the existing rows in place, and
|
|
498
498
|
updates the stored row objects used by later events. That path creates no descriptors or DOM rows,
|
|
499
|
-
and preserves row identity, focus, and selection.
|
|
499
|
+
and preserves row identity, focus, and selection. Validated same-key row and window refreshes also
|
|
500
|
+
keep the existing row map and element lookup, and skip redundant cache cleanup instead of
|
|
501
|
+
rebuilding whole-list bookkeeping. Source and key validation still run, and each flush commits the
|
|
502
|
+
new collection token for subsequent updates. Structural changes retain index rebuilding and cache
|
|
503
|
+
cleanup. A window may instead grow or shrink while it
|
|
500
504
|
reorders keys from inside its own removed interval and mixes them with globally fresh keys. Farm
|
|
501
505
|
prepares all reused binding updates, new descriptors, binding snapshots, and detached rows before
|
|
502
506
|
the first DOM write. It removes only retired rows, preserves each reused row, batches adjacent new
|
|
@@ -562,12 +566,15 @@ subclassed behavior, structural calls after reordering, an unhinted intermediate
|
|
|
562
566
|
React-owned rows, and failed checks keep complete keyed reconciliation.
|
|
563
567
|
|
|
564
568
|
A compiler-safe `filter()` or bounded `slice()` prefix may precede the native reorder suffix in a
|
|
565
|
-
concise updater or exact one-return block
|
|
569
|
+
concise updater or exact one-return block. A filter predicate may be concise or contain exactly one
|
|
570
|
+
direct value-returning `return`:
|
|
566
571
|
|
|
567
572
|
```tsx
|
|
568
573
|
setItems((current) =>
|
|
569
574
|
current
|
|
570
|
-
.filter((item) =>
|
|
575
|
+
.filter((item) => {
|
|
576
|
+
return item.visible;
|
|
577
|
+
})
|
|
571
578
|
.toSorted((left, right) => left.rank - right.rank)
|
|
572
579
|
.toReversed(),
|
|
573
580
|
);
|
|
@@ -809,17 +816,22 @@ setItems((current) => current.filter((item) => item.id !== removedId));
|
|
|
809
816
|
setItems((current) => {
|
|
810
817
|
return current.filter((item) => item.id !== removedId);
|
|
811
818
|
});
|
|
819
|
+
setItems((current) =>
|
|
820
|
+
current.filter((item) => {
|
|
821
|
+
return item.id !== removedId;
|
|
822
|
+
}),
|
|
823
|
+
);
|
|
812
824
|
```
|
|
813
825
|
|
|
814
826
|
For compiler-owned host rows whose render and key do not observe the row index, Farm validates the
|
|
815
827
|
native filter chain, every surviving item identity, and every surviving key before removing only
|
|
816
828
|
the rejected DOM rows. It does not recreate descriptors or reread bindings for unchanged rows,
|
|
817
829
|
and queued filters compose before one compiler flush. Index-aware rows or predicates, updater blocks
|
|
818
|
-
with extra statements, directives, conditional returns, or no value-returning `return`,
|
|
819
|
-
|
|
820
|
-
React-owned row structures, mixed dirty dependencies, and
|
|
821
|
-
reconciliation. No option or new component is required. The
|
|
822
|
-
count as `keyedArrayFilterHints`.
|
|
830
|
+
with extra statements, directives, conditional returns, or no value-returning `return`, predicate
|
|
831
|
+
blocks with those unsupported shapes, custom filter methods, sparse or subclassed arrays,
|
|
832
|
+
collection-reading bindings or keys, React-owned row structures, mixed dirty dependencies, and
|
|
833
|
+
failed validation use complete keyed reconciliation. No option or new component is required. The
|
|
834
|
+
compiler report exposes the emitted-site count as `keyedArrayFilterHints`.
|
|
823
835
|
|
|
824
836
|
An otherwise eligible host row may also contain an inline synchronous React event:
|
|
825
837
|
|
|
@@ -3381,7 +3381,6 @@ function createHostConditionalBlockComponent(owner) {
|
|
|
3381
3381
|
for (const unsubscribe of this.fallbackUnsubscribers) unsubscribe();
|
|
3382
3382
|
this.fallbackUnsubscribers = [];
|
|
3383
3383
|
this.instance?.scope?.cleanup();
|
|
3384
|
-
this.root = null;
|
|
3385
3384
|
this.activeBranch = null;
|
|
3386
3385
|
this.instance = null;
|
|
3387
3386
|
}
|
|
@@ -3653,7 +3652,6 @@ function createConditionalRangesBlockComponent(owner) {
|
|
|
3653
3652
|
for (const unsubscribe of this.fallbackUnsubscribers) unsubscribe();
|
|
3654
3653
|
this.fallbackUnsubscribers = [];
|
|
3655
3654
|
for (const instance of this.rangeInstances) instance?.host.scope?.cleanup();
|
|
3656
|
-
this.root = null;
|
|
3657
3655
|
this.rangeInstances = [];
|
|
3658
3656
|
this.staticSegments = [];
|
|
3659
3657
|
this.staticValues.length = 0;
|
|
@@ -4495,15 +4493,15 @@ function reconcileCompilerKeyedArrayBatchInsert(props, dirtyState, collectionTok
|
|
|
4495
4493
|
return void 0;
|
|
4496
4494
|
}
|
|
4497
4495
|
}
|
|
4498
|
-
const
|
|
4496
|
+
const incomingKeys = /* @__PURE__ */ new Set();
|
|
4499
4497
|
const incoming = [];
|
|
4500
4498
|
try {
|
|
4501
4499
|
for (let offset = 0; offset < insertCount; offset += 1) {
|
|
4502
4500
|
const index = update.position + offset;
|
|
4503
4501
|
const item = finalValue[index];
|
|
4504
4502
|
const key = keyedRowIdentity(props.rowKey(item, index));
|
|
4505
|
-
if (
|
|
4506
|
-
|
|
4503
|
+
if (instances.has(key) || incomingKeys.has(key)) return void 0;
|
|
4504
|
+
incomingKeys.add(key);
|
|
4507
4505
|
const descriptor = props.create(item, index);
|
|
4508
4506
|
incoming.push({
|
|
4509
4507
|
key,
|
|
@@ -4656,9 +4654,9 @@ function reconcileCompilerKeyedArrayWindowReplace(props, dirtyState, collectionT
|
|
|
4656
4654
|
const preparedIncomingKeys = /* @__PURE__ */ new Set();
|
|
4657
4655
|
const preparedWindows = [];
|
|
4658
4656
|
const nextInstances = [];
|
|
4659
|
-
for (const
|
|
4660
|
-
if (
|
|
4661
|
-
while (sourceCursor <
|
|
4657
|
+
for (const window2 of windows) {
|
|
4658
|
+
if (window2[0] < sourceCursor) return void 0;
|
|
4659
|
+
while (sourceCursor < window2[0]) {
|
|
4662
4660
|
const instance = previousInstances[sourceCursor];
|
|
4663
4661
|
if (!instance || instance.index !== sourceCursor || !Object.is(instance.item, finalValue[resultCursor])) {
|
|
4664
4662
|
return void 0;
|
|
@@ -4671,24 +4669,24 @@ function reconcileCompilerKeyedArrayWindowReplace(props, dirtyState, collectionT
|
|
|
4671
4669
|
props,
|
|
4672
4670
|
finalValue,
|
|
4673
4671
|
resultCursor,
|
|
4674
|
-
|
|
4672
|
+
window2[3]
|
|
4675
4673
|
);
|
|
4676
4674
|
if (!incoming2) return void 0;
|
|
4677
|
-
|
|
4675
|
+
window2[1] = resultCursor;
|
|
4678
4676
|
const prepared3 = prepareCompilerKeyedArrayWindow(
|
|
4679
4677
|
props,
|
|
4680
4678
|
instances,
|
|
4681
4679
|
previousInstances,
|
|
4682
4680
|
root,
|
|
4683
|
-
|
|
4681
|
+
window2,
|
|
4684
4682
|
incoming2,
|
|
4685
4683
|
preparedIncomingKeys
|
|
4686
4684
|
);
|
|
4687
4685
|
if (!prepared3) return void 0;
|
|
4688
4686
|
preparedWindows.push(prepared3);
|
|
4689
4687
|
nextInstances.push(...prepared3[4]);
|
|
4690
|
-
sourceCursor +=
|
|
4691
|
-
resultCursor +=
|
|
4688
|
+
sourceCursor += window2[2];
|
|
4689
|
+
resultCursor += window2[3];
|
|
4692
4690
|
}
|
|
4693
4691
|
while (sourceCursor < previousInstances.length) {
|
|
4694
4692
|
const instance = previousInstances[sourceCursor];
|
|
@@ -4708,30 +4706,32 @@ function reconcileCompilerKeyedArrayWindowReplace(props, dirtyState, collectionT
|
|
|
4708
4706
|
}
|
|
4709
4707
|
return keyedRowInstancesByKey(nextInstances);
|
|
4710
4708
|
}
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
touchedIndices.add(index);
|
|
4715
|
-
}
|
|
4716
|
-
}
|
|
4709
|
+
updates.sort((left, right) => right.position - left.position);
|
|
4710
|
+
let window = updates.pop();
|
|
4711
|
+
const touchedInstances = [];
|
|
4717
4712
|
for (let index = 0; index < previousInstances.length; index += 1) {
|
|
4713
|
+
while (window && index >= window.position + window.removedCount) {
|
|
4714
|
+
window = updates.pop();
|
|
4715
|
+
}
|
|
4718
4716
|
const instance = previousInstances[index];
|
|
4719
|
-
|
|
4720
|
-
if (
|
|
4717
|
+
if (!instance || instance.index !== index) return void 0;
|
|
4718
|
+
if (window && index >= window.position) {
|
|
4719
|
+
if (instance.element.parentNode !== root) return void 0;
|
|
4720
|
+
touchedInstances.push(instance);
|
|
4721
|
+
} else if (!Object.is(instance.item, finalValue[index])) {
|
|
4721
4722
|
return void 0;
|
|
4722
4723
|
}
|
|
4723
4724
|
}
|
|
4724
|
-
const knownKeys = new Set(instances.keys());
|
|
4725
4725
|
const incomingKeys2 = /* @__PURE__ */ new Set();
|
|
4726
4726
|
let replacesRows = false;
|
|
4727
4727
|
const prepared2 = [];
|
|
4728
4728
|
try {
|
|
4729
|
-
for (const
|
|
4730
|
-
const
|
|
4729
|
+
for (const instance of touchedInstances) {
|
|
4730
|
+
const index = instance.index;
|
|
4731
4731
|
const item = finalValue[index];
|
|
4732
4732
|
const key = keyedRowIdentity(props.rowKey(item, index));
|
|
4733
4733
|
if (key !== instance.key) {
|
|
4734
|
-
if (
|
|
4734
|
+
if (instances.has(key) || incomingKeys2.has(key)) return void 0;
|
|
4735
4735
|
incomingKeys2.add(key);
|
|
4736
4736
|
replacesRows = true;
|
|
4737
4737
|
const descriptor = props.create(item, index);
|
|
@@ -5555,11 +5555,13 @@ function createKeyedRowsBlockComponent(owner, options = {}) {
|
|
|
5555
5555
|
this.hasReactOwnedRows()
|
|
5556
5556
|
);
|
|
5557
5557
|
if (positionedInstances) {
|
|
5558
|
-
this.instances
|
|
5559
|
-
|
|
5560
|
-
|
|
5561
|
-
|
|
5562
|
-
|
|
5558
|
+
if (positionedInstances !== this.instances) {
|
|
5559
|
+
this.instances = new Map(positionedInstances);
|
|
5560
|
+
this.rebuildElementIndex(this.instances);
|
|
5561
|
+
const keys = [...this.instances.keys()];
|
|
5562
|
+
this.pruneEventHandlers(keys);
|
|
5563
|
+
this.pruneConditionalListeners(keys);
|
|
5564
|
+
}
|
|
5563
5565
|
this.commitCurrentCollection(dirtyState);
|
|
5564
5566
|
afterCommit?.();
|
|
5565
5567
|
return;
|
|
@@ -5574,9 +5576,9 @@ function createKeyedRowsBlockComponent(owner, options = {}) {
|
|
|
5574
5576
|
);
|
|
5575
5577
|
if (reorderedInstances) {
|
|
5576
5578
|
const removedRows = reorderedInstances.size < this.instances.size;
|
|
5577
|
-
this.instances =
|
|
5578
|
-
this.rebuildElementIndex(this.instances);
|
|
5579
|
+
this.instances = reorderedInstances;
|
|
5579
5580
|
if (removedRows) {
|
|
5581
|
+
this.rebuildElementIndex(this.instances);
|
|
5580
5582
|
const keys = [...this.instances.keys()];
|
|
5581
5583
|
this.pruneEventHandlers(keys);
|
|
5582
5584
|
this.pruneConditionalListeners(keys);
|
|
@@ -6303,7 +6305,6 @@ function createKeyedRowsBlockComponent(owner, options = {}) {
|
|
|
6303
6305
|
componentWillUnmount() {
|
|
6304
6306
|
this.mounted = false;
|
|
6305
6307
|
this.unsubscribe?.();
|
|
6306
|
-
this.root = null;
|
|
6307
6308
|
this.cleanupHostScopes();
|
|
6308
6309
|
this.instances.clear();
|
|
6309
6310
|
this.identityTargets.clear();
|
|
@@ -6537,7 +6538,6 @@ function createKeyedRangesBlockComponent(owner) {
|
|
|
6537
6538
|
componentWillUnmount() {
|
|
6538
6539
|
this.mounted = false;
|
|
6539
6540
|
this.unsubscribe?.();
|
|
6540
|
-
this.root = null;
|
|
6541
6541
|
this.rangeInstances = [];
|
|
6542
6542
|
this.staticSegments = [];
|
|
6543
6543
|
this.staticValues.length = 0;
|
|
@@ -6662,7 +6662,6 @@ function createMixedRangesBlockComponent(owner) {
|
|
|
6662
6662
|
this.controller?.cleanup();
|
|
6663
6663
|
this.controller = null;
|
|
6664
6664
|
this.clearFallbackSubscriptions();
|
|
6665
|
-
this.root = null;
|
|
6666
6665
|
}
|
|
6667
6666
|
render() {
|
|
6668
6667
|
const container = this.currentProps.render();
|
|
@@ -7776,13 +7775,11 @@ function createCompiledComponentWithFeatures(definition, runtimeFeatures) {
|
|
|
7776
7775
|
}
|
|
7777
7776
|
componentWillUnmount() {
|
|
7778
7777
|
this.mounted = false;
|
|
7779
|
-
this.root = null;
|
|
7780
7778
|
this.dirtyState.clear();
|
|
7781
7779
|
this.inputSelection = null;
|
|
7782
7780
|
this.blockRefreshListeners.clear();
|
|
7783
7781
|
this.blockRoots.clear();
|
|
7784
7782
|
this.blockRootElements.clear();
|
|
7785
|
-
this.bindingTargets.clear();
|
|
7786
7783
|
this.bindingTargetRefs.clear();
|
|
7787
7784
|
this.indexedDefinition = null;
|
|
7788
7785
|
this.staticBindingsByDependency = [];
|