@farm.js/react 0.1.0-beta.2 → 0.1.0-beta.4
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 +148 -42
- package/dist/compiler-runtime.cjs +2087 -134
- package/dist/compiler-runtime.cjs.map +1 -1
- package/dist/compiler-runtime.d.mts +94 -1
- package/dist/compiler-runtime.d.ts +94 -1
- package/dist/compiler-runtime.mjs +2087 -134
- package/dist/compiler-runtime.mjs.map +1 -1
- package/dist/index.cjs +5 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +8 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.mjs +5 -1
- package/dist/index.mjs.map +1 -1
- package/dist/list.cjs +18 -1
- package/dist/list.cjs.map +1 -1
- package/dist/list.mjs +18 -1
- package/dist/list.mjs.map +1 -1
- package/dist/vite.cjs +1321 -75
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.mjs +1321 -75
- package/dist/vite.mjs.map +1 -1
- package/package.json +4 -3
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { flushSync } from 'react-dom';
|
|
3
3
|
|
|
4
|
+
// src/compiler-runtime.tsx
|
|
5
|
+
|
|
6
|
+
// src/iterable.ts
|
|
7
|
+
var oneShotSnapshots = /* @__PURE__ */ new WeakMap();
|
|
8
|
+
function materializeIterable(source) {
|
|
9
|
+
if (source == null) return [];
|
|
10
|
+
const iterator = source[Symbol.iterator]();
|
|
11
|
+
const oneShot = iterator === source && (typeof source === "object" || typeof source === "function");
|
|
12
|
+
if (oneShot) {
|
|
13
|
+
const cached = oneShotSnapshots.get(source);
|
|
14
|
+
if (cached) return cached;
|
|
15
|
+
}
|
|
16
|
+
const items = Array.from({ [Symbol.iterator]: () => iterator });
|
|
17
|
+
if (oneShot) oneShotSnapshots.set(source, items);
|
|
18
|
+
return items;
|
|
19
|
+
}
|
|
20
|
+
|
|
4
21
|
// src/compiler-runtime.tsx
|
|
5
22
|
var COMPILER_HMR_REGISTRY = /* @__PURE__ */ Symbol.for("@farm.js/react/compiler-hmr-registry");
|
|
6
23
|
function getCompilerHmrRegistry() {
|
|
@@ -16,6 +33,11 @@ function renderTextValue(value) {
|
|
|
16
33
|
if (value === null || value === void 0 || typeof value === "boolean") return "";
|
|
17
34
|
return String(value);
|
|
18
35
|
}
|
|
36
|
+
function isCompilerPrimitive(value) {
|
|
37
|
+
if (value === null) return true;
|
|
38
|
+
const kind = typeof value;
|
|
39
|
+
return kind === "string" || kind === "number" || kind === "boolean" || kind === "bigint" || kind === "undefined";
|
|
40
|
+
}
|
|
19
41
|
function findBindingTarget(root, path, blockRoots) {
|
|
20
42
|
let current = root;
|
|
21
43
|
for (const index of path) {
|
|
@@ -254,14 +276,19 @@ function createCompilerHostElement(document, descriptor) {
|
|
|
254
276
|
updateAttribute(element, attribute.name, attribute.value);
|
|
255
277
|
}
|
|
256
278
|
for (const style of descriptor.styles) updateStyle(element, style.name, style.value);
|
|
257
|
-
|
|
279
|
+
const appendChild = (child) => {
|
|
280
|
+
if (Array.isArray(child)) {
|
|
281
|
+
for (const nested of child) appendChild(nested);
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
258
284
|
if (isCompilerHostElement(child)) {
|
|
259
285
|
element.append(createCompilerHostElement(document, child));
|
|
260
|
-
|
|
286
|
+
return;
|
|
261
287
|
}
|
|
262
288
|
const text = renderTextValue(child);
|
|
263
289
|
if (text) element.append(document.createTextNode(text));
|
|
264
|
-
}
|
|
290
|
+
};
|
|
291
|
+
for (const child of materializeCompilerHostChildren(descriptor)) appendChild(child);
|
|
265
292
|
for (const attribute of descriptor.attributes) {
|
|
266
293
|
if (attribute.name === "value" && (isSelectElement(element) || isTextAreaElement(element))) {
|
|
267
294
|
updateAttribute(element, attribute.name, attribute.value);
|
|
@@ -271,18 +298,110 @@ function createCompilerHostElement(document, descriptor) {
|
|
|
271
298
|
}
|
|
272
299
|
function matchesCompilerHostElement(element, descriptor, opaquePaths = /* @__PURE__ */ new Set(), path = []) {
|
|
273
300
|
if (element.tagName.toLowerCase() !== descriptor.tag.toLowerCase()) return false;
|
|
274
|
-
if (opaquePaths.has(path.join("."))) return true;
|
|
275
|
-
const expectedChildren = descriptor.children
|
|
301
|
+
if (opaquePaths.has(path.join(".")) || descriptor.block) return true;
|
|
302
|
+
const expectedChildren = flattenCompilerHostElements(descriptor.children);
|
|
276
303
|
if (element.children.length !== expectedChildren.length) return false;
|
|
277
304
|
return expectedChildren.every(
|
|
278
305
|
(child, index) => matchesCompilerHostElement(element.children[index], child, opaquePaths, [...path, index])
|
|
279
306
|
);
|
|
280
307
|
}
|
|
308
|
+
function flattenCompilerHostElements(children) {
|
|
309
|
+
const elements = [];
|
|
310
|
+
const visit = (child) => {
|
|
311
|
+
if (Array.isArray(child)) {
|
|
312
|
+
for (const nested of child) visit(nested);
|
|
313
|
+
} else if (isCompilerHostElement(child)) {
|
|
314
|
+
elements.push(child);
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
for (const child of children) visit(child);
|
|
318
|
+
return elements;
|
|
319
|
+
}
|
|
320
|
+
function materializeCompilerHostChildren(descriptor) {
|
|
321
|
+
const block = descriptor.block;
|
|
322
|
+
if (block?.kind !== "keyed-ranges" || !block.staticChildrenOnly) {
|
|
323
|
+
return descriptor.children;
|
|
324
|
+
}
|
|
325
|
+
const staticChildren = flattenCompilerHostElements(descriptor.children);
|
|
326
|
+
const children = [];
|
|
327
|
+
let cursor = 0;
|
|
328
|
+
for (const range of block.ranges) {
|
|
329
|
+
children.push(...staticChildren.slice(cursor, cursor + range.before));
|
|
330
|
+
cursor += range.before;
|
|
331
|
+
const items = materializeIterable(range.items());
|
|
332
|
+
children.push(...items.map((item, index) => range.create(item, index)));
|
|
333
|
+
}
|
|
334
|
+
children.push(...staticChildren.slice(cursor, cursor + block.trailing));
|
|
335
|
+
return children;
|
|
336
|
+
}
|
|
337
|
+
function collectCompilerHostBlockIds(descriptor, ids) {
|
|
338
|
+
for (const child of flattenCompilerHostElements(descriptor.children)) {
|
|
339
|
+
collectCompilerHostBlockIds(child, ids);
|
|
340
|
+
}
|
|
341
|
+
const block = descriptor.block;
|
|
342
|
+
if (!block || ids.has(block.id)) return;
|
|
343
|
+
ids.add(block.id);
|
|
344
|
+
if (block.kind === "conditional-ranges") {
|
|
345
|
+
for (const range of block.ranges) {
|
|
346
|
+
if (range.truthy) collectCompilerHostBlockIds(range.truthy.create(), ids);
|
|
347
|
+
if (range.falsy) collectCompilerHostBlockIds(range.falsy.create(), ids);
|
|
348
|
+
}
|
|
349
|
+
} else if (block.kind === "keyed-ranges") {
|
|
350
|
+
for (const range of block.ranges) {
|
|
351
|
+
const first = materializeIterable(range.items())[0];
|
|
352
|
+
if (first !== void 0) collectCompilerHostBlockIds(range.create(first, 0), ids);
|
|
353
|
+
}
|
|
354
|
+
} else {
|
|
355
|
+
for (const range of block.ranges) {
|
|
356
|
+
if (range.kind === "conditional") {
|
|
357
|
+
if (range.truthy) collectCompilerHostBlockIds(range.truthy.create(), ids);
|
|
358
|
+
if (range.falsy) collectCompilerHostBlockIds(range.falsy.create(), ids);
|
|
359
|
+
} else {
|
|
360
|
+
const first = materializeIterable(range.items())[0];
|
|
361
|
+
if (first !== void 0) collectCompilerHostBlockIds(range.create(first, 0), ids);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
281
366
|
function findCompilerHostTarget(root, path) {
|
|
282
367
|
let current = root;
|
|
283
368
|
for (const index of path) current = current?.children[index] || null;
|
|
284
369
|
return current;
|
|
285
370
|
}
|
|
371
|
+
var UNSET_STATIC_RANGE_BINDING = /* @__PURE__ */ Symbol("unset static range binding");
|
|
372
|
+
function normalizedStaticRangeBindingValue(binding, value) {
|
|
373
|
+
return binding.kind === "text" ? renderTextValue(value) : value;
|
|
374
|
+
}
|
|
375
|
+
function applyStaticRangeBindings(bindings, segments, values) {
|
|
376
|
+
const activeBindings = bindings || [];
|
|
377
|
+
if (values.length === 0 && activeBindings.length > 0) {
|
|
378
|
+
values.push(...activeBindings.map(() => UNSET_STATIC_RANGE_BINDING));
|
|
379
|
+
}
|
|
380
|
+
if (values.length !== activeBindings.length) return false;
|
|
381
|
+
for (let index = 0; index < activeBindings.length; index += 1) {
|
|
382
|
+
const binding = activeBindings[index];
|
|
383
|
+
if (!Number.isSafeInteger(binding.segment) || binding.segment < 0 || !Number.isSafeInteger(binding.sibling) || binding.sibling < 0) {
|
|
384
|
+
return false;
|
|
385
|
+
}
|
|
386
|
+
const sibling = segments[binding.segment]?.[binding.sibling];
|
|
387
|
+
const target = sibling && findCompilerHostTarget(sibling, binding.path);
|
|
388
|
+
if (!target) return false;
|
|
389
|
+
const rawValue = binding.read();
|
|
390
|
+
const value = normalizedStaticRangeBindingValue(binding, rawValue);
|
|
391
|
+
if (Object.is(values[index], value)) continue;
|
|
392
|
+
values[index] = value;
|
|
393
|
+
if (binding.kind === "text") {
|
|
394
|
+
target.textContent = value;
|
|
395
|
+
} else if (binding.kind === "style" && binding.name) {
|
|
396
|
+
updateStyle(target, binding.name, rawValue);
|
|
397
|
+
} else if (binding.kind === "attribute" && binding.name) {
|
|
398
|
+
updateAttribute(target, binding.name, rawValue);
|
|
399
|
+
} else {
|
|
400
|
+
return false;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
return true;
|
|
404
|
+
}
|
|
286
405
|
var UNSET_KEYED_ROW_BINDING = /* @__PURE__ */ Symbol("unset interactive keyed-row binding");
|
|
287
406
|
function keyedRowIdentity(key) {
|
|
288
407
|
return String(key);
|
|
@@ -297,20 +416,23 @@ function readKeyedRowBindingValues(props, item, index) {
|
|
|
297
416
|
}
|
|
298
417
|
function applyKeyedRowBindings(props, instance, item, index) {
|
|
299
418
|
for (let bindingIndex = 0; bindingIndex < props.bindings.length; bindingIndex += 1) {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
419
|
+
applyKeyedRowBinding(props, instance, item, index, bindingIndex);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
function applyKeyedRowBinding(props, instance, item, index, bindingIndex) {
|
|
423
|
+
const binding = props.bindings[bindingIndex];
|
|
424
|
+
const rawValue = binding.read(item, index);
|
|
425
|
+
const value = normalizedKeyedRowBindingValue(binding, rawValue);
|
|
426
|
+
if (Object.is(instance.values[bindingIndex], value)) return;
|
|
427
|
+
instance.values[bindingIndex] = value;
|
|
428
|
+
const target = findCompilerHostTarget(instance.element, binding.path);
|
|
429
|
+
if (!target) return;
|
|
430
|
+
if (binding.kind === "text") {
|
|
431
|
+
target.textContent = value;
|
|
432
|
+
} else if (binding.kind === "style" && binding.name) {
|
|
433
|
+
updateStyle(target, binding.name, rawValue);
|
|
434
|
+
} else if (binding.kind === "attribute" && binding.name) {
|
|
435
|
+
updateAttribute(target, binding.name, rawValue);
|
|
314
436
|
}
|
|
315
437
|
}
|
|
316
438
|
function keyedRowConditionalSnapshot(conditional, item, index) {
|
|
@@ -329,13 +451,15 @@ function keyedRowConditionalSnapshot(conditional, item, index) {
|
|
|
329
451
|
];
|
|
330
452
|
}
|
|
331
453
|
function readKeyedRowConditionalValues(props, item, index) {
|
|
454
|
+
if (!props.conditionals?.length) return EMPTY_KEYED_ROW_CONDITIONAL_VALUES;
|
|
332
455
|
return new Map(
|
|
333
|
-
|
|
456
|
+
props.conditionals.map((conditional) => [
|
|
334
457
|
conditional.id,
|
|
335
458
|
keyedRowConditionalSnapshot(conditional, item, index)
|
|
336
459
|
])
|
|
337
460
|
);
|
|
338
461
|
}
|
|
462
|
+
var EMPTY_KEYED_ROW_CONDITIONAL_VALUES = /* @__PURE__ */ new Map();
|
|
339
463
|
function keyedRowConditionalChanged(previous, next) {
|
|
340
464
|
return !previous || previous.length !== next.length || next.some((value, index) => !Object.is(value, previous[index]));
|
|
341
465
|
}
|
|
@@ -352,11 +476,6 @@ function hostConditionalSelection(props) {
|
|
|
352
476
|
function normalizedHostConditionalBindingValue(binding, value) {
|
|
353
477
|
return binding.kind === "text" ? renderTextValue(value) : value;
|
|
354
478
|
}
|
|
355
|
-
function readHostConditionalBindingValues(branch) {
|
|
356
|
-
return branch.bindings.map(
|
|
357
|
-
(binding) => normalizedHostConditionalBindingValue(binding, binding.read())
|
|
358
|
-
);
|
|
359
|
-
}
|
|
360
479
|
function applyHostConditionalBindings(branch, instance) {
|
|
361
480
|
for (let bindingIndex = 0; bindingIndex < branch.bindings.length; bindingIndex += 1) {
|
|
362
481
|
const binding = branch.bindings[bindingIndex];
|
|
@@ -375,6 +494,903 @@ function applyHostConditionalBindings(branch, instance) {
|
|
|
375
494
|
}
|
|
376
495
|
}
|
|
377
496
|
}
|
|
497
|
+
var UNSET_HOST_CONDITIONAL_BINDING = /* @__PURE__ */ Symbol("unset host conditional binding");
|
|
498
|
+
function mountCompilerHostTree(owner, element, descriptor, onFallback) {
|
|
499
|
+
if (!matchesCompilerHostElement(element, descriptor)) return null;
|
|
500
|
+
if (descriptor.block?.kind === "conditional-ranges") {
|
|
501
|
+
const controller = new CompilerNestedConditionalRanges(
|
|
502
|
+
owner,
|
|
503
|
+
element,
|
|
504
|
+
descriptor,
|
|
505
|
+
descriptor.block,
|
|
506
|
+
onFallback
|
|
507
|
+
);
|
|
508
|
+
try {
|
|
509
|
+
if (controller.adopt()) return controller;
|
|
510
|
+
controller.cleanup();
|
|
511
|
+
return null;
|
|
512
|
+
} catch (error) {
|
|
513
|
+
controller.cleanup();
|
|
514
|
+
throw error;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
if (descriptor.block?.kind === "keyed-ranges") {
|
|
518
|
+
const controller = new CompilerNestedKeyedRanges(
|
|
519
|
+
owner,
|
|
520
|
+
element,
|
|
521
|
+
descriptor,
|
|
522
|
+
descriptor.block,
|
|
523
|
+
onFallback
|
|
524
|
+
);
|
|
525
|
+
try {
|
|
526
|
+
if (controller.adopt()) return controller;
|
|
527
|
+
controller.cleanup();
|
|
528
|
+
return null;
|
|
529
|
+
} catch (error) {
|
|
530
|
+
controller.cleanup();
|
|
531
|
+
throw error;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
if (descriptor.block?.kind === "mixed-ranges") {
|
|
535
|
+
const controller = new CompilerNestedMixedRanges(
|
|
536
|
+
owner,
|
|
537
|
+
element,
|
|
538
|
+
descriptor,
|
|
539
|
+
descriptor.block,
|
|
540
|
+
onFallback
|
|
541
|
+
);
|
|
542
|
+
try {
|
|
543
|
+
if (controller.adopt()) return controller;
|
|
544
|
+
controller.cleanup();
|
|
545
|
+
return null;
|
|
546
|
+
} catch (error) {
|
|
547
|
+
controller.cleanup();
|
|
548
|
+
throw error;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
const descriptors = flattenCompilerHostElements(descriptor.children);
|
|
552
|
+
if (descriptors.length !== element.children.length) return null;
|
|
553
|
+
const scopes = [];
|
|
554
|
+
for (let index = 0; index < descriptors.length; index += 1) {
|
|
555
|
+
const scope = mountCompilerHostTree(
|
|
556
|
+
owner,
|
|
557
|
+
element.children[index],
|
|
558
|
+
descriptors[index],
|
|
559
|
+
onFallback
|
|
560
|
+
);
|
|
561
|
+
if (!scope) {
|
|
562
|
+
for (const mounted of scopes) mounted.cleanup();
|
|
563
|
+
return null;
|
|
564
|
+
}
|
|
565
|
+
scopes.push(scope);
|
|
566
|
+
}
|
|
567
|
+
let active = true;
|
|
568
|
+
return {
|
|
569
|
+
update(nextDescriptor) {
|
|
570
|
+
if (!active || nextDescriptor.block || !matchesCompilerHostElement(element, nextDescriptor)) {
|
|
571
|
+
return false;
|
|
572
|
+
}
|
|
573
|
+
const nextChildren = flattenCompilerHostElements(nextDescriptor.children);
|
|
574
|
+
if (nextChildren.length !== scopes.length) return false;
|
|
575
|
+
return scopes.every((scope, index) => scope.update(nextChildren[index]));
|
|
576
|
+
},
|
|
577
|
+
cleanup() {
|
|
578
|
+
if (!active) return;
|
|
579
|
+
active = false;
|
|
580
|
+
for (const scope of scopes) scope.cleanup();
|
|
581
|
+
}
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
function mountCompilerHostInstance(owner, element, descriptor, branch, onFallback) {
|
|
585
|
+
const scope = mountCompilerHostTree(owner, element, descriptor, onFallback);
|
|
586
|
+
if (!scope) return null;
|
|
587
|
+
const instance = {
|
|
588
|
+
element,
|
|
589
|
+
scope,
|
|
590
|
+
values: branch.bindings.map(() => UNSET_HOST_CONDITIONAL_BINDING)
|
|
591
|
+
};
|
|
592
|
+
try {
|
|
593
|
+
applyHostConditionalBindings(branch, instance);
|
|
594
|
+
} catch (error) {
|
|
595
|
+
scope.cleanup();
|
|
596
|
+
throw error;
|
|
597
|
+
}
|
|
598
|
+
return instance;
|
|
599
|
+
}
|
|
600
|
+
var CompilerNestedConditionalRanges = class {
|
|
601
|
+
constructor(owner, root, host, block, onFallback) {
|
|
602
|
+
this.owner = owner;
|
|
603
|
+
this.root = root;
|
|
604
|
+
this.host = host;
|
|
605
|
+
this.block = block;
|
|
606
|
+
this.onFallback = onFallback;
|
|
607
|
+
this.instances = [];
|
|
608
|
+
this.staticSegments = [];
|
|
609
|
+
this.staticScopes = [];
|
|
610
|
+
this.staticValues = [];
|
|
611
|
+
this.active = true;
|
|
612
|
+
this.refresh = (afterCommit) => {
|
|
613
|
+
if (!this.active) {
|
|
614
|
+
afterCommit?.();
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
const selections = this.readSelections();
|
|
618
|
+
if (!selections || selections.length !== this.instances.length) {
|
|
619
|
+
this.onFallback();
|
|
620
|
+
afterCommit?.();
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
623
|
+
if (!applyStaticRangeBindings(this.block.bindings, this.staticSegments, this.staticValues)) {
|
|
624
|
+
this.onFallback();
|
|
625
|
+
afterCommit?.();
|
|
626
|
+
return;
|
|
627
|
+
}
|
|
628
|
+
for (let index = this.instances.length - 1; index >= 0; index -= 1) {
|
|
629
|
+
if (!this.reconcileRange(index, selections[index])) {
|
|
630
|
+
this.onFallback();
|
|
631
|
+
afterCommit?.();
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
afterCommit?.();
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
readSelections() {
|
|
639
|
+
const selections = [];
|
|
640
|
+
for (const range of this.block.ranges) {
|
|
641
|
+
const selection = hostConditionalSelection(range);
|
|
642
|
+
if (selection.kind === "fallback") return null;
|
|
643
|
+
selections.push(selection);
|
|
644
|
+
}
|
|
645
|
+
return selections;
|
|
646
|
+
}
|
|
647
|
+
mountStatic(elements, descriptors) {
|
|
648
|
+
if (elements.length !== descriptors.length) return false;
|
|
649
|
+
for (let index = 0; index < elements.length; index += 1) {
|
|
650
|
+
const scope = mountCompilerHostTree(
|
|
651
|
+
this.owner,
|
|
652
|
+
elements[index],
|
|
653
|
+
descriptors[index],
|
|
654
|
+
this.onFallback
|
|
655
|
+
);
|
|
656
|
+
if (!scope) return false;
|
|
657
|
+
this.staticScopes.push(scope);
|
|
658
|
+
}
|
|
659
|
+
return true;
|
|
660
|
+
}
|
|
661
|
+
adopt() {
|
|
662
|
+
if (!Number.isSafeInteger(this.block.trailing) || this.block.trailing < 0) return false;
|
|
663
|
+
const selections = this.readSelections();
|
|
664
|
+
if (!selections) return false;
|
|
665
|
+
const elements = [...this.root.children];
|
|
666
|
+
const descriptors = flattenCompilerHostElements(this.host.children);
|
|
667
|
+
if (elements.length !== descriptors.length) return false;
|
|
668
|
+
let cursor = 0;
|
|
669
|
+
for (let index = 0; index < this.block.ranges.length; index += 1) {
|
|
670
|
+
const range = this.block.ranges[index];
|
|
671
|
+
if (!Number.isSafeInteger(range.before) || range.before < 0) {
|
|
672
|
+
this.cleanup();
|
|
673
|
+
return false;
|
|
674
|
+
}
|
|
675
|
+
const staticEnd = cursor + range.before;
|
|
676
|
+
if (staticEnd > elements.length || !this.mountStatic(elements.slice(cursor, staticEnd), descriptors.slice(cursor, staticEnd))) {
|
|
677
|
+
this.cleanup();
|
|
678
|
+
return false;
|
|
679
|
+
}
|
|
680
|
+
this.staticSegments.push(elements.slice(cursor, staticEnd));
|
|
681
|
+
cursor = staticEnd;
|
|
682
|
+
const selection = selections[index];
|
|
683
|
+
if (selection.kind === "empty") {
|
|
684
|
+
this.instances.push(null);
|
|
685
|
+
continue;
|
|
686
|
+
}
|
|
687
|
+
const element = elements[cursor];
|
|
688
|
+
if (!element) {
|
|
689
|
+
this.cleanup();
|
|
690
|
+
return false;
|
|
691
|
+
}
|
|
692
|
+
const descriptor = selection.branch.create();
|
|
693
|
+
const host = mountCompilerHostInstance(
|
|
694
|
+
this.owner,
|
|
695
|
+
element,
|
|
696
|
+
descriptor,
|
|
697
|
+
selection.branch,
|
|
698
|
+
this.onFallback
|
|
699
|
+
);
|
|
700
|
+
if (!host) {
|
|
701
|
+
this.cleanup();
|
|
702
|
+
return false;
|
|
703
|
+
}
|
|
704
|
+
this.instances.push({ key: selection.key, host });
|
|
705
|
+
cursor += 1;
|
|
706
|
+
}
|
|
707
|
+
const trailingEnd = cursor + this.block.trailing;
|
|
708
|
+
if (trailingEnd !== elements.length || !this.mountStatic(elements.slice(cursor), descriptors.slice(cursor))) {
|
|
709
|
+
this.cleanup();
|
|
710
|
+
return false;
|
|
711
|
+
}
|
|
712
|
+
this.staticSegments.push(elements.slice(cursor));
|
|
713
|
+
if (!applyStaticRangeBindings(this.block.bindings, this.staticSegments, this.staticValues)) {
|
|
714
|
+
this.cleanup();
|
|
715
|
+
return false;
|
|
716
|
+
}
|
|
717
|
+
this.unsubscribe = this.owner.subscribe(this.block.id, this.refresh);
|
|
718
|
+
return true;
|
|
719
|
+
}
|
|
720
|
+
anchorAfter(rangeIndex) {
|
|
721
|
+
for (let next = rangeIndex + 1; next < this.instances.length; next += 1) {
|
|
722
|
+
const staticAnchor = this.staticSegments[next]?.[0];
|
|
723
|
+
if (staticAnchor) return staticAnchor;
|
|
724
|
+
const rangeAnchor = this.instances[next]?.host.element;
|
|
725
|
+
if (rangeAnchor) return rangeAnchor;
|
|
726
|
+
}
|
|
727
|
+
return this.staticSegments[this.instances.length]?.[0] || null;
|
|
728
|
+
}
|
|
729
|
+
reconcileRange(rangeIndex, selection) {
|
|
730
|
+
const previous = this.instances[rangeIndex];
|
|
731
|
+
if (selection.kind === "empty") {
|
|
732
|
+
previous?.host.scope?.cleanup();
|
|
733
|
+
previous?.host.element.remove();
|
|
734
|
+
this.instances[rangeIndex] = null;
|
|
735
|
+
return true;
|
|
736
|
+
}
|
|
737
|
+
if (previous?.key === selection.key) {
|
|
738
|
+
const descriptor2 = selection.branch.create();
|
|
739
|
+
if (!previous.host.scope?.update(descriptor2)) return false;
|
|
740
|
+
applyHostConditionalBindings(selection.branch, previous.host);
|
|
741
|
+
return true;
|
|
742
|
+
}
|
|
743
|
+
const descriptor = selection.branch.create();
|
|
744
|
+
const element = createCompilerHostElement(this.root.ownerDocument, descriptor);
|
|
745
|
+
const host = mountCompilerHostInstance(
|
|
746
|
+
this.owner,
|
|
747
|
+
element,
|
|
748
|
+
descriptor,
|
|
749
|
+
selection.branch,
|
|
750
|
+
this.onFallback
|
|
751
|
+
);
|
|
752
|
+
if (!host) return false;
|
|
753
|
+
previous?.host.scope?.cleanup();
|
|
754
|
+
if (previous) previous.host.element.replaceWith(element);
|
|
755
|
+
else this.root.insertBefore(element, this.anchorAfter(rangeIndex));
|
|
756
|
+
this.instances[rangeIndex] = { key: selection.key, host };
|
|
757
|
+
return true;
|
|
758
|
+
}
|
|
759
|
+
updateStaticScopes(descriptor, selections) {
|
|
760
|
+
const descriptors = flattenCompilerHostElements(descriptor.children);
|
|
761
|
+
let descriptorIndex = 0;
|
|
762
|
+
let scopeIndex = 0;
|
|
763
|
+
for (let rangeIndex = 0; rangeIndex < this.block.ranges.length; rangeIndex += 1) {
|
|
764
|
+
const range = this.block.ranges[rangeIndex];
|
|
765
|
+
for (let index = 0; index < range.before; index += 1) {
|
|
766
|
+
const scope = this.staticScopes[scopeIndex++];
|
|
767
|
+
const child = descriptors[descriptorIndex++];
|
|
768
|
+
if (!scope || !child || !scope.update(child)) return false;
|
|
769
|
+
}
|
|
770
|
+
if (selections[rangeIndex].kind === "branch") descriptorIndex += 1;
|
|
771
|
+
}
|
|
772
|
+
for (let index = 0; index < this.block.trailing; index += 1) {
|
|
773
|
+
const scope = this.staticScopes[scopeIndex++];
|
|
774
|
+
const child = descriptors[descriptorIndex++];
|
|
775
|
+
if (!scope || !child || !scope.update(child)) return false;
|
|
776
|
+
}
|
|
777
|
+
return scopeIndex === this.staticScopes.length && descriptorIndex === descriptors.length;
|
|
778
|
+
}
|
|
779
|
+
update(descriptor) {
|
|
780
|
+
const block = descriptor.block;
|
|
781
|
+
if (!this.active || block?.kind !== "conditional-ranges" || block.id !== this.block.id || block.ranges.length !== this.block.ranges.length || block.trailing !== this.block.trailing || block.ranges.some((range, index) => range.before !== this.block.ranges[index].before)) {
|
|
782
|
+
return false;
|
|
783
|
+
}
|
|
784
|
+
this.host = descriptor;
|
|
785
|
+
this.block = block;
|
|
786
|
+
const selections = this.readSelections();
|
|
787
|
+
if (!selections || !this.updateStaticScopes(descriptor, selections) || !applyStaticRangeBindings(this.block.bindings, this.staticSegments, this.staticValues)) {
|
|
788
|
+
return false;
|
|
789
|
+
}
|
|
790
|
+
for (let index = this.instances.length - 1; index >= 0; index -= 1) {
|
|
791
|
+
if (!this.reconcileRange(index, selections[index])) return false;
|
|
792
|
+
}
|
|
793
|
+
return true;
|
|
794
|
+
}
|
|
795
|
+
cleanup() {
|
|
796
|
+
if (!this.active) return;
|
|
797
|
+
this.active = false;
|
|
798
|
+
this.unsubscribe?.();
|
|
799
|
+
for (const instance of this.instances) instance?.host.scope?.cleanup();
|
|
800
|
+
for (const scope of this.staticScopes) scope.cleanup();
|
|
801
|
+
this.instances.length = 0;
|
|
802
|
+
this.staticSegments.length = 0;
|
|
803
|
+
this.staticScopes.length = 0;
|
|
804
|
+
this.staticValues.length = 0;
|
|
805
|
+
}
|
|
806
|
+
};
|
|
807
|
+
var CompilerNestedKeyedRanges = class {
|
|
808
|
+
constructor(owner, root, host, block, onFallback) {
|
|
809
|
+
this.owner = owner;
|
|
810
|
+
this.root = root;
|
|
811
|
+
this.host = host;
|
|
812
|
+
this.block = block;
|
|
813
|
+
this.onFallback = onFallback;
|
|
814
|
+
this.instances = [];
|
|
815
|
+
this.staticSegments = [];
|
|
816
|
+
this.staticScopes = [];
|
|
817
|
+
this.staticValues = [];
|
|
818
|
+
this.active = true;
|
|
819
|
+
this.refresh = (afterCommit) => {
|
|
820
|
+
if (!this.active) {
|
|
821
|
+
afterCommit?.();
|
|
822
|
+
return;
|
|
823
|
+
}
|
|
824
|
+
const rowsByRange = this.readRanges();
|
|
825
|
+
if (!rowsByRange || rowsByRange.length !== this.instances.length) {
|
|
826
|
+
this.onFallback();
|
|
827
|
+
afterCommit?.();
|
|
828
|
+
return;
|
|
829
|
+
}
|
|
830
|
+
if (!applyStaticRangeBindings(this.block.bindings, this.staticSegments, this.staticValues)) {
|
|
831
|
+
this.onFallback();
|
|
832
|
+
afterCommit?.();
|
|
833
|
+
return;
|
|
834
|
+
}
|
|
835
|
+
const activeElement = this.root.ownerDocument.activeElement;
|
|
836
|
+
const restoreFocus = Boolean(activeElement && this.root.contains(activeElement));
|
|
837
|
+
for (let index = rowsByRange.length - 1; index >= 0; index -= 1) {
|
|
838
|
+
if (!this.reconcileRange(index, rowsByRange[index])) {
|
|
839
|
+
this.onFallback();
|
|
840
|
+
afterCommit?.();
|
|
841
|
+
return;
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
if (restoreFocus && activeElement?.isConnected && activeElement.ownerDocument.activeElement !== activeElement && "focus" in activeElement) {
|
|
845
|
+
activeElement.focus({ preventScroll: true });
|
|
846
|
+
}
|
|
847
|
+
afterCommit?.();
|
|
848
|
+
};
|
|
849
|
+
}
|
|
850
|
+
readRange(range) {
|
|
851
|
+
const items = materializeIterable(range.items());
|
|
852
|
+
const keys = items.map((item, index) => keyedRowIdentity(range.rowKey(item, index)));
|
|
853
|
+
return new Set(keys).size === keys.length ? { items, keys } : null;
|
|
854
|
+
}
|
|
855
|
+
readRanges() {
|
|
856
|
+
const ranges = [];
|
|
857
|
+
for (const range of this.block.ranges) {
|
|
858
|
+
const rows = this.readRange(range);
|
|
859
|
+
if (!rows) return null;
|
|
860
|
+
ranges.push(rows);
|
|
861
|
+
}
|
|
862
|
+
return ranges;
|
|
863
|
+
}
|
|
864
|
+
mountStatic(elements, descriptors) {
|
|
865
|
+
if (elements.length !== descriptors.length) return false;
|
|
866
|
+
for (let index = 0; index < elements.length; index += 1) {
|
|
867
|
+
const scope = mountCompilerHostTree(
|
|
868
|
+
this.owner,
|
|
869
|
+
elements[index],
|
|
870
|
+
descriptors[index],
|
|
871
|
+
this.onFallback
|
|
872
|
+
);
|
|
873
|
+
if (!scope) return false;
|
|
874
|
+
this.staticScopes.push(scope);
|
|
875
|
+
}
|
|
876
|
+
return true;
|
|
877
|
+
}
|
|
878
|
+
adopt() {
|
|
879
|
+
if (!Number.isSafeInteger(this.block.trailing) || this.block.trailing < 0) return false;
|
|
880
|
+
const rowsByRange = this.readRanges();
|
|
881
|
+
if (!rowsByRange) return false;
|
|
882
|
+
const elements = [...this.root.children];
|
|
883
|
+
const descriptors = flattenCompilerHostElements(materializeCompilerHostChildren(this.host));
|
|
884
|
+
if (elements.length !== descriptors.length) return false;
|
|
885
|
+
let cursor = 0;
|
|
886
|
+
for (let rangeIndex = 0; rangeIndex < this.block.ranges.length; rangeIndex += 1) {
|
|
887
|
+
const range = this.block.ranges[rangeIndex];
|
|
888
|
+
const rows = rowsByRange[rangeIndex];
|
|
889
|
+
if (!Number.isSafeInteger(range.before) || range.before < 0) {
|
|
890
|
+
this.cleanup();
|
|
891
|
+
return false;
|
|
892
|
+
}
|
|
893
|
+
const staticEnd = cursor + range.before;
|
|
894
|
+
if (staticEnd > elements.length || !this.mountStatic(elements.slice(cursor, staticEnd), descriptors.slice(cursor, staticEnd))) {
|
|
895
|
+
this.cleanup();
|
|
896
|
+
return false;
|
|
897
|
+
}
|
|
898
|
+
this.staticSegments.push(elements.slice(cursor, staticEnd));
|
|
899
|
+
cursor = staticEnd;
|
|
900
|
+
const instances = /* @__PURE__ */ new Map();
|
|
901
|
+
for (let index = 0; index < rows.items.length; index += 1) {
|
|
902
|
+
const element = elements[cursor + index];
|
|
903
|
+
if (!element) {
|
|
904
|
+
this.cleanup();
|
|
905
|
+
return false;
|
|
906
|
+
}
|
|
907
|
+
const descriptor = range.create(rows.items[index], index);
|
|
908
|
+
const scope = mountCompilerHostTree(this.owner, element, descriptor, this.onFallback);
|
|
909
|
+
if (!scope) {
|
|
910
|
+
this.cleanup();
|
|
911
|
+
return false;
|
|
912
|
+
}
|
|
913
|
+
instances.set(rows.keys[index], {
|
|
914
|
+
key: rows.keys[index],
|
|
915
|
+
element,
|
|
916
|
+
scope,
|
|
917
|
+
values: range.bindings.map(() => UNSET_KEYED_ROW_BINDING),
|
|
918
|
+
item: rows.items[index],
|
|
919
|
+
index,
|
|
920
|
+
conditionalValues: /* @__PURE__ */ new Map()
|
|
921
|
+
});
|
|
922
|
+
applyKeyedRowBindings(range, instances.get(rows.keys[index]), rows.items[index], index);
|
|
923
|
+
}
|
|
924
|
+
this.instances.push(instances);
|
|
925
|
+
cursor += rows.items.length;
|
|
926
|
+
}
|
|
927
|
+
const trailingEnd = cursor + this.block.trailing;
|
|
928
|
+
if (trailingEnd !== elements.length || !this.mountStatic(elements.slice(cursor), descriptors.slice(cursor))) {
|
|
929
|
+
this.cleanup();
|
|
930
|
+
return false;
|
|
931
|
+
}
|
|
932
|
+
this.staticSegments.push(elements.slice(cursor));
|
|
933
|
+
if (!applyStaticRangeBindings(this.block.bindings, this.staticSegments, this.staticValues)) {
|
|
934
|
+
this.cleanup();
|
|
935
|
+
return false;
|
|
936
|
+
}
|
|
937
|
+
this.unsubscribe = this.owner.subscribe(this.block.id, this.refresh);
|
|
938
|
+
return true;
|
|
939
|
+
}
|
|
940
|
+
anchorAfter(rangeIndex) {
|
|
941
|
+
for (let next = rangeIndex + 1; next < this.instances.length; next += 1) {
|
|
942
|
+
const staticAnchor = this.staticSegments[next]?.[0];
|
|
943
|
+
if (staticAnchor) return staticAnchor;
|
|
944
|
+
const rowAnchor = this.instances[next].values().next().value?.element;
|
|
945
|
+
if (rowAnchor) return rowAnchor;
|
|
946
|
+
}
|
|
947
|
+
return this.staticSegments[this.instances.length]?.[0] || null;
|
|
948
|
+
}
|
|
949
|
+
reconcileRange(rangeIndex, rows) {
|
|
950
|
+
const range = this.block.ranges[rangeIndex];
|
|
951
|
+
const previous = this.instances[rangeIndex];
|
|
952
|
+
const oldIndices = /* @__PURE__ */ new Map();
|
|
953
|
+
[...previous.keys()].forEach((key, index) => oldIndices.set(key, index));
|
|
954
|
+
const nextKeys = new Set(rows.keys);
|
|
955
|
+
for (const [key, instance] of previous) {
|
|
956
|
+
if (nextKeys.has(key)) continue;
|
|
957
|
+
instance.scope?.cleanup();
|
|
958
|
+
instance.element.remove();
|
|
959
|
+
}
|
|
960
|
+
const sequence = rows.keys.map((key) => oldIndices.get(key) ?? -1);
|
|
961
|
+
const stablePositions = longestIncreasingSubsequencePositions(sequence);
|
|
962
|
+
const nextInstances = [];
|
|
963
|
+
for (let index = 0; index < rows.items.length; index += 1) {
|
|
964
|
+
const key = rows.keys[index];
|
|
965
|
+
const existing = previous.get(key);
|
|
966
|
+
if (existing) {
|
|
967
|
+
const descriptor2 = range.create(rows.items[index], index);
|
|
968
|
+
if (!existing.scope?.update(descriptor2)) return false;
|
|
969
|
+
applyKeyedRowBindings(range, existing, rows.items[index], index);
|
|
970
|
+
existing.item = rows.items[index];
|
|
971
|
+
existing.index = index;
|
|
972
|
+
nextInstances.push(existing);
|
|
973
|
+
continue;
|
|
974
|
+
}
|
|
975
|
+
const descriptor = range.create(rows.items[index], index);
|
|
976
|
+
const element = createCompilerHostElement(this.root.ownerDocument, descriptor);
|
|
977
|
+
const scope = mountCompilerHostTree(this.owner, element, descriptor, this.onFallback);
|
|
978
|
+
if (!scope) return false;
|
|
979
|
+
nextInstances.push({
|
|
980
|
+
key,
|
|
981
|
+
element,
|
|
982
|
+
scope,
|
|
983
|
+
values: readKeyedRowBindingValues(range, rows.items[index], index),
|
|
984
|
+
item: rows.items[index],
|
|
985
|
+
index,
|
|
986
|
+
conditionalValues: /* @__PURE__ */ new Map()
|
|
987
|
+
});
|
|
988
|
+
}
|
|
989
|
+
let anchor = this.anchorAfter(rangeIndex);
|
|
990
|
+
for (let index = nextInstances.length - 1; index >= 0; index -= 1) {
|
|
991
|
+
const instance = nextInstances[index];
|
|
992
|
+
if (sequence[index] < 0 || !stablePositions.has(index) && instance.element.nextSibling !== anchor) {
|
|
993
|
+
this.root.insertBefore(instance.element, anchor);
|
|
994
|
+
}
|
|
995
|
+
anchor = instance.element;
|
|
996
|
+
}
|
|
997
|
+
this.instances[rangeIndex] = new Map(nextInstances.map((instance) => [instance.key, instance]));
|
|
998
|
+
return true;
|
|
999
|
+
}
|
|
1000
|
+
updateStaticScopes(descriptor, rowsByRange) {
|
|
1001
|
+
const descriptors = flattenCompilerHostElements(materializeCompilerHostChildren(descriptor));
|
|
1002
|
+
let descriptorIndex = 0;
|
|
1003
|
+
let scopeIndex = 0;
|
|
1004
|
+
for (let rangeIndex = 0; rangeIndex < this.block.ranges.length; rangeIndex += 1) {
|
|
1005
|
+
const range = this.block.ranges[rangeIndex];
|
|
1006
|
+
for (let index = 0; index < range.before; index += 1) {
|
|
1007
|
+
const scope = this.staticScopes[scopeIndex++];
|
|
1008
|
+
const child = descriptors[descriptorIndex++];
|
|
1009
|
+
if (!scope || !child || !scope.update(child)) return false;
|
|
1010
|
+
}
|
|
1011
|
+
descriptorIndex += rowsByRange[rangeIndex].items.length;
|
|
1012
|
+
}
|
|
1013
|
+
for (let index = 0; index < this.block.trailing; index += 1) {
|
|
1014
|
+
const scope = this.staticScopes[scopeIndex++];
|
|
1015
|
+
const child = descriptors[descriptorIndex++];
|
|
1016
|
+
if (!scope || !child || !scope.update(child)) return false;
|
|
1017
|
+
}
|
|
1018
|
+
return scopeIndex === this.staticScopes.length && descriptorIndex === descriptors.length;
|
|
1019
|
+
}
|
|
1020
|
+
update(descriptor) {
|
|
1021
|
+
const block = descriptor.block;
|
|
1022
|
+
if (!this.active || block?.kind !== "keyed-ranges" || block.id !== this.block.id || block.ranges.length !== this.block.ranges.length || block.trailing !== this.block.trailing || block.ranges.some((range, index) => range.before !== this.block.ranges[index].before)) {
|
|
1023
|
+
return false;
|
|
1024
|
+
}
|
|
1025
|
+
this.host = descriptor;
|
|
1026
|
+
this.block = block;
|
|
1027
|
+
const rowsByRange = this.readRanges();
|
|
1028
|
+
if (!rowsByRange || rowsByRange.length !== this.instances.length || !this.updateStaticScopes(descriptor, rowsByRange) || !applyStaticRangeBindings(this.block.bindings, this.staticSegments, this.staticValues)) {
|
|
1029
|
+
return false;
|
|
1030
|
+
}
|
|
1031
|
+
for (let index = rowsByRange.length - 1; index >= 0; index -= 1) {
|
|
1032
|
+
if (!this.reconcileRange(index, rowsByRange[index])) return false;
|
|
1033
|
+
}
|
|
1034
|
+
return true;
|
|
1035
|
+
}
|
|
1036
|
+
cleanup() {
|
|
1037
|
+
if (!this.active) return;
|
|
1038
|
+
this.active = false;
|
|
1039
|
+
this.unsubscribe?.();
|
|
1040
|
+
for (const instances of this.instances) {
|
|
1041
|
+
for (const instance of instances.values()) instance.scope?.cleanup();
|
|
1042
|
+
}
|
|
1043
|
+
for (const scope of this.staticScopes) scope.cleanup();
|
|
1044
|
+
this.instances.length = 0;
|
|
1045
|
+
this.staticSegments.length = 0;
|
|
1046
|
+
this.staticScopes.length = 0;
|
|
1047
|
+
this.staticValues.length = 0;
|
|
1048
|
+
}
|
|
1049
|
+
};
|
|
1050
|
+
var CompilerNestedMixedRanges = class {
|
|
1051
|
+
constructor(owner, root, host, block, onFallback) {
|
|
1052
|
+
this.owner = owner;
|
|
1053
|
+
this.root = root;
|
|
1054
|
+
this.host = host;
|
|
1055
|
+
this.block = block;
|
|
1056
|
+
this.onFallback = onFallback;
|
|
1057
|
+
this.instances = [];
|
|
1058
|
+
this.staticSegments = [];
|
|
1059
|
+
this.staticScopes = [];
|
|
1060
|
+
this.staticValues = [];
|
|
1061
|
+
this.active = true;
|
|
1062
|
+
this.refresh = (afterCommit) => {
|
|
1063
|
+
if (!this.active) {
|
|
1064
|
+
afterCommit?.();
|
|
1065
|
+
return;
|
|
1066
|
+
}
|
|
1067
|
+
const snapshots = this.readSnapshots();
|
|
1068
|
+
if (!snapshots || snapshots.length !== this.instances.length) {
|
|
1069
|
+
this.onFallback();
|
|
1070
|
+
afterCommit?.();
|
|
1071
|
+
return;
|
|
1072
|
+
}
|
|
1073
|
+
if (!applyStaticRangeBindings(this.block.bindings, this.staticSegments, this.staticValues)) {
|
|
1074
|
+
this.onFallback();
|
|
1075
|
+
afterCommit?.();
|
|
1076
|
+
return;
|
|
1077
|
+
}
|
|
1078
|
+
const activeElement = this.root.ownerDocument.activeElement;
|
|
1079
|
+
const restoreFocus = Boolean(activeElement && this.root.contains(activeElement));
|
|
1080
|
+
for (let index = snapshots.length - 1; index >= 0; index -= 1) {
|
|
1081
|
+
if (!this.reconcileRange(index, snapshots[index])) {
|
|
1082
|
+
this.onFallback();
|
|
1083
|
+
afterCommit?.();
|
|
1084
|
+
return;
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
if (restoreFocus && activeElement?.isConnected && activeElement.ownerDocument.activeElement !== activeElement && "focus" in activeElement) {
|
|
1088
|
+
activeElement.focus({ preventScroll: true });
|
|
1089
|
+
}
|
|
1090
|
+
afterCommit?.();
|
|
1091
|
+
};
|
|
1092
|
+
}
|
|
1093
|
+
readSnapshots() {
|
|
1094
|
+
const snapshots = [];
|
|
1095
|
+
for (const range of this.block.ranges) {
|
|
1096
|
+
if (range.kind === "conditional") {
|
|
1097
|
+
const selection = hostConditionalSelection(range);
|
|
1098
|
+
if (selection.kind === "fallback") return null;
|
|
1099
|
+
snapshots.push({ kind: "conditional", selection });
|
|
1100
|
+
continue;
|
|
1101
|
+
}
|
|
1102
|
+
const items = materializeIterable(range.items());
|
|
1103
|
+
const keys = items.map((item, index) => keyedRowIdentity(range.rowKey(item, index)));
|
|
1104
|
+
if (new Set(keys).size !== keys.length) return null;
|
|
1105
|
+
snapshots.push({ kind: "keyed", rows: { items, keys } });
|
|
1106
|
+
}
|
|
1107
|
+
return snapshots;
|
|
1108
|
+
}
|
|
1109
|
+
mountStatic(elements, descriptors) {
|
|
1110
|
+
if (elements.length !== descriptors.length) return false;
|
|
1111
|
+
for (let index = 0; index < elements.length; index += 1) {
|
|
1112
|
+
const scope = mountCompilerHostTree(
|
|
1113
|
+
this.owner,
|
|
1114
|
+
elements[index],
|
|
1115
|
+
descriptors[index],
|
|
1116
|
+
this.onFallback
|
|
1117
|
+
);
|
|
1118
|
+
if (!scope) return false;
|
|
1119
|
+
this.staticScopes.push(scope);
|
|
1120
|
+
}
|
|
1121
|
+
return true;
|
|
1122
|
+
}
|
|
1123
|
+
adopt() {
|
|
1124
|
+
if (!Number.isSafeInteger(this.block.trailing) || this.block.trailing < 0) return false;
|
|
1125
|
+
const snapshots = this.readSnapshots();
|
|
1126
|
+
if (!snapshots) return false;
|
|
1127
|
+
const elements = [...this.root.children];
|
|
1128
|
+
const descriptors = flattenCompilerHostElements(this.host.children);
|
|
1129
|
+
if (elements.length !== descriptors.length) return false;
|
|
1130
|
+
let cursor = 0;
|
|
1131
|
+
for (let rangeIndex = 0; rangeIndex < this.block.ranges.length; rangeIndex += 1) {
|
|
1132
|
+
const range = this.block.ranges[rangeIndex];
|
|
1133
|
+
const snapshot = snapshots[rangeIndex];
|
|
1134
|
+
if (!Number.isSafeInteger(range.before) || range.before < 0 || range.kind !== snapshot.kind) {
|
|
1135
|
+
this.cleanup();
|
|
1136
|
+
return false;
|
|
1137
|
+
}
|
|
1138
|
+
const staticEnd = cursor + range.before;
|
|
1139
|
+
if (staticEnd > elements.length || !this.mountStatic(elements.slice(cursor, staticEnd), descriptors.slice(cursor, staticEnd))) {
|
|
1140
|
+
this.cleanup();
|
|
1141
|
+
return false;
|
|
1142
|
+
}
|
|
1143
|
+
this.staticSegments.push(elements.slice(cursor, staticEnd));
|
|
1144
|
+
cursor = staticEnd;
|
|
1145
|
+
if (range.kind === "conditional" && snapshot.kind === "conditional") {
|
|
1146
|
+
if (snapshot.selection.kind === "empty") {
|
|
1147
|
+
this.instances.push({ kind: "conditional", value: null });
|
|
1148
|
+
continue;
|
|
1149
|
+
}
|
|
1150
|
+
const element = elements[cursor];
|
|
1151
|
+
if (!element) {
|
|
1152
|
+
this.cleanup();
|
|
1153
|
+
return false;
|
|
1154
|
+
}
|
|
1155
|
+
const descriptor = snapshot.selection.branch.create();
|
|
1156
|
+
const host = mountCompilerHostInstance(
|
|
1157
|
+
this.owner,
|
|
1158
|
+
element,
|
|
1159
|
+
descriptor,
|
|
1160
|
+
snapshot.selection.branch,
|
|
1161
|
+
this.onFallback
|
|
1162
|
+
);
|
|
1163
|
+
if (!host) {
|
|
1164
|
+
this.cleanup();
|
|
1165
|
+
return false;
|
|
1166
|
+
}
|
|
1167
|
+
this.instances.push({
|
|
1168
|
+
kind: "conditional",
|
|
1169
|
+
value: { key: snapshot.selection.key, host }
|
|
1170
|
+
});
|
|
1171
|
+
cursor += 1;
|
|
1172
|
+
continue;
|
|
1173
|
+
}
|
|
1174
|
+
if (range.kind !== "keyed" || snapshot.kind !== "keyed") {
|
|
1175
|
+
this.cleanup();
|
|
1176
|
+
return false;
|
|
1177
|
+
}
|
|
1178
|
+
const keyedInstances = /* @__PURE__ */ new Map();
|
|
1179
|
+
for (let index = 0; index < snapshot.rows.items.length; index += 1) {
|
|
1180
|
+
const element = elements[cursor + index];
|
|
1181
|
+
if (!element) {
|
|
1182
|
+
this.cleanup();
|
|
1183
|
+
return false;
|
|
1184
|
+
}
|
|
1185
|
+
const descriptor = range.create(snapshot.rows.items[index], index);
|
|
1186
|
+
const scope = mountCompilerHostTree(this.owner, element, descriptor, this.onFallback);
|
|
1187
|
+
if (!scope) {
|
|
1188
|
+
this.cleanup();
|
|
1189
|
+
return false;
|
|
1190
|
+
}
|
|
1191
|
+
const instance = {
|
|
1192
|
+
key: snapshot.rows.keys[index],
|
|
1193
|
+
element,
|
|
1194
|
+
scope,
|
|
1195
|
+
values: range.bindings.map(() => UNSET_KEYED_ROW_BINDING),
|
|
1196
|
+
item: snapshot.rows.items[index],
|
|
1197
|
+
index,
|
|
1198
|
+
conditionalValues: /* @__PURE__ */ new Map()
|
|
1199
|
+
};
|
|
1200
|
+
try {
|
|
1201
|
+
applyKeyedRowBindings(range, instance, snapshot.rows.items[index], index);
|
|
1202
|
+
} catch (error) {
|
|
1203
|
+
scope.cleanup();
|
|
1204
|
+
throw error;
|
|
1205
|
+
}
|
|
1206
|
+
keyedInstances.set(snapshot.rows.keys[index], instance);
|
|
1207
|
+
}
|
|
1208
|
+
this.instances.push({ kind: "keyed", value: keyedInstances });
|
|
1209
|
+
cursor += snapshot.rows.items.length;
|
|
1210
|
+
}
|
|
1211
|
+
const trailingEnd = cursor + this.block.trailing;
|
|
1212
|
+
if (trailingEnd !== elements.length || !this.mountStatic(elements.slice(cursor), descriptors.slice(cursor))) {
|
|
1213
|
+
this.cleanup();
|
|
1214
|
+
return false;
|
|
1215
|
+
}
|
|
1216
|
+
this.staticSegments.push(elements.slice(cursor));
|
|
1217
|
+
if (!applyStaticRangeBindings(this.block.bindings, this.staticSegments, this.staticValues)) {
|
|
1218
|
+
this.cleanup();
|
|
1219
|
+
return false;
|
|
1220
|
+
}
|
|
1221
|
+
this.unsubscribe = this.owner.subscribe(this.block.id, this.refresh);
|
|
1222
|
+
return true;
|
|
1223
|
+
}
|
|
1224
|
+
firstInstanceElement(instance) {
|
|
1225
|
+
if (instance.kind === "conditional") return instance.value?.host.element || null;
|
|
1226
|
+
return instance.value.values().next().value?.element || null;
|
|
1227
|
+
}
|
|
1228
|
+
anchorAfter(rangeIndex) {
|
|
1229
|
+
for (let next = rangeIndex + 1; next < this.instances.length; next += 1) {
|
|
1230
|
+
const staticAnchor = this.staticSegments[next]?.[0];
|
|
1231
|
+
if (staticAnchor) return staticAnchor;
|
|
1232
|
+
const rangeAnchor = this.firstInstanceElement(this.instances[next]);
|
|
1233
|
+
if (rangeAnchor) return rangeAnchor;
|
|
1234
|
+
}
|
|
1235
|
+
return this.staticSegments[this.instances.length]?.[0] || null;
|
|
1236
|
+
}
|
|
1237
|
+
reconcileConditional(rangeIndex, range, selection) {
|
|
1238
|
+
const instance = this.instances[rangeIndex];
|
|
1239
|
+
if (instance.kind !== "conditional") return false;
|
|
1240
|
+
const previous = instance.value;
|
|
1241
|
+
if (selection.kind === "empty") {
|
|
1242
|
+
previous?.host.scope?.cleanup();
|
|
1243
|
+
previous?.host.element.remove();
|
|
1244
|
+
instance.value = null;
|
|
1245
|
+
return true;
|
|
1246
|
+
}
|
|
1247
|
+
if (previous?.key === selection.key) {
|
|
1248
|
+
const descriptor2 = selection.branch.create();
|
|
1249
|
+
if (!previous.host.scope?.update(descriptor2)) return false;
|
|
1250
|
+
applyHostConditionalBindings(selection.branch, previous.host);
|
|
1251
|
+
return true;
|
|
1252
|
+
}
|
|
1253
|
+
const descriptor = selection.branch.create();
|
|
1254
|
+
const element = createCompilerHostElement(this.root.ownerDocument, descriptor);
|
|
1255
|
+
const host = mountCompilerHostInstance(
|
|
1256
|
+
this.owner,
|
|
1257
|
+
element,
|
|
1258
|
+
descriptor,
|
|
1259
|
+
selection.branch,
|
|
1260
|
+
this.onFallback
|
|
1261
|
+
);
|
|
1262
|
+
if (!host) return false;
|
|
1263
|
+
previous?.host.scope?.cleanup();
|
|
1264
|
+
if (previous) previous.host.element.replaceWith(element);
|
|
1265
|
+
else this.root.insertBefore(element, this.anchorAfter(rangeIndex));
|
|
1266
|
+
instance.value = { key: selection.key, host };
|
|
1267
|
+
return true;
|
|
1268
|
+
}
|
|
1269
|
+
reconcileKeyed(rangeIndex, range, rows) {
|
|
1270
|
+
const instance = this.instances[rangeIndex];
|
|
1271
|
+
if (instance.kind !== "keyed") return false;
|
|
1272
|
+
const previous = instance.value;
|
|
1273
|
+
const oldIndices = /* @__PURE__ */ new Map();
|
|
1274
|
+
[...previous.keys()].forEach((key, index) => oldIndices.set(key, index));
|
|
1275
|
+
const nextKeys = new Set(rows.keys);
|
|
1276
|
+
for (const [key, row] of previous) {
|
|
1277
|
+
if (nextKeys.has(key)) continue;
|
|
1278
|
+
row.scope?.cleanup();
|
|
1279
|
+
row.element.remove();
|
|
1280
|
+
}
|
|
1281
|
+
const sequence = rows.keys.map((key) => oldIndices.get(key) ?? -1);
|
|
1282
|
+
const stablePositions = longestIncreasingSubsequencePositions(sequence);
|
|
1283
|
+
const nextInstances = [];
|
|
1284
|
+
for (let index = 0; index < rows.items.length; index += 1) {
|
|
1285
|
+
const key = rows.keys[index];
|
|
1286
|
+
const existing = previous.get(key);
|
|
1287
|
+
if (existing) {
|
|
1288
|
+
const descriptor2 = range.create(rows.items[index], index);
|
|
1289
|
+
if (!existing.scope?.update(descriptor2)) return false;
|
|
1290
|
+
applyKeyedRowBindings(range, existing, rows.items[index], index);
|
|
1291
|
+
existing.item = rows.items[index];
|
|
1292
|
+
existing.index = index;
|
|
1293
|
+
nextInstances.push(existing);
|
|
1294
|
+
continue;
|
|
1295
|
+
}
|
|
1296
|
+
const descriptor = range.create(rows.items[index], index);
|
|
1297
|
+
const element = createCompilerHostElement(this.root.ownerDocument, descriptor);
|
|
1298
|
+
const scope = mountCompilerHostTree(this.owner, element, descriptor, this.onFallback);
|
|
1299
|
+
if (!scope) return false;
|
|
1300
|
+
let values;
|
|
1301
|
+
try {
|
|
1302
|
+
values = readKeyedRowBindingValues(range, rows.items[index], index);
|
|
1303
|
+
} catch (error) {
|
|
1304
|
+
scope.cleanup();
|
|
1305
|
+
throw error;
|
|
1306
|
+
}
|
|
1307
|
+
nextInstances.push({
|
|
1308
|
+
key,
|
|
1309
|
+
element,
|
|
1310
|
+
scope,
|
|
1311
|
+
values,
|
|
1312
|
+
item: rows.items[index],
|
|
1313
|
+
index,
|
|
1314
|
+
conditionalValues: /* @__PURE__ */ new Map()
|
|
1315
|
+
});
|
|
1316
|
+
}
|
|
1317
|
+
let anchor = this.anchorAfter(rangeIndex);
|
|
1318
|
+
for (let index = nextInstances.length - 1; index >= 0; index -= 1) {
|
|
1319
|
+
const row = nextInstances[index];
|
|
1320
|
+
if (sequence[index] < 0 || !stablePositions.has(index) && row.element.nextSibling !== anchor) {
|
|
1321
|
+
this.root.insertBefore(row.element, anchor);
|
|
1322
|
+
}
|
|
1323
|
+
anchor = row.element;
|
|
1324
|
+
}
|
|
1325
|
+
instance.value = new Map(nextInstances.map((row) => [row.key, row]));
|
|
1326
|
+
return true;
|
|
1327
|
+
}
|
|
1328
|
+
reconcileRange(rangeIndex, snapshot) {
|
|
1329
|
+
const range = this.block.ranges[rangeIndex];
|
|
1330
|
+
if (range.kind !== snapshot.kind) return false;
|
|
1331
|
+
return range.kind === "conditional" && snapshot.kind === "conditional" ? this.reconcileConditional(rangeIndex, range, snapshot.selection) : range.kind === "keyed" && snapshot.kind === "keyed" ? this.reconcileKeyed(rangeIndex, range, snapshot.rows) : false;
|
|
1332
|
+
}
|
|
1333
|
+
updateStaticScopes(descriptor, snapshots) {
|
|
1334
|
+
const descriptors = flattenCompilerHostElements(descriptor.children);
|
|
1335
|
+
let descriptorIndex = 0;
|
|
1336
|
+
let scopeIndex = 0;
|
|
1337
|
+
for (let rangeIndex = 0; rangeIndex < this.block.ranges.length; rangeIndex += 1) {
|
|
1338
|
+
const range = this.block.ranges[rangeIndex];
|
|
1339
|
+
for (let index = 0; index < range.before; index += 1) {
|
|
1340
|
+
const scope = this.staticScopes[scopeIndex++];
|
|
1341
|
+
const child = descriptors[descriptorIndex++];
|
|
1342
|
+
if (!scope || !child || !scope.update(child)) return false;
|
|
1343
|
+
}
|
|
1344
|
+
const snapshot = snapshots[rangeIndex];
|
|
1345
|
+
if (snapshot.kind === "conditional") {
|
|
1346
|
+
if (snapshot.selection.kind === "branch") descriptorIndex += 1;
|
|
1347
|
+
} else {
|
|
1348
|
+
descriptorIndex += snapshot.rows.items.length;
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
for (let index = 0; index < this.block.trailing; index += 1) {
|
|
1352
|
+
const scope = this.staticScopes[scopeIndex++];
|
|
1353
|
+
const child = descriptors[descriptorIndex++];
|
|
1354
|
+
if (!scope || !child || !scope.update(child)) return false;
|
|
1355
|
+
}
|
|
1356
|
+
return scopeIndex === this.staticScopes.length && descriptorIndex === descriptors.length;
|
|
1357
|
+
}
|
|
1358
|
+
update(descriptor) {
|
|
1359
|
+
const block = descriptor.block;
|
|
1360
|
+
if (!this.active || block?.kind !== "mixed-ranges" || block.id !== this.block.id || block.ranges.length !== this.block.ranges.length || block.trailing !== this.block.trailing || block.ranges.some(
|
|
1361
|
+
(range, index) => range.kind !== this.block.ranges[index].kind || range.before !== this.block.ranges[index].before
|
|
1362
|
+
)) {
|
|
1363
|
+
return false;
|
|
1364
|
+
}
|
|
1365
|
+
this.host = descriptor;
|
|
1366
|
+
this.block = block;
|
|
1367
|
+
const snapshots = this.readSnapshots();
|
|
1368
|
+
if (!snapshots || snapshots.length !== this.instances.length || !this.updateStaticScopes(descriptor, snapshots) || !applyStaticRangeBindings(this.block.bindings, this.staticSegments, this.staticValues)) {
|
|
1369
|
+
return false;
|
|
1370
|
+
}
|
|
1371
|
+
for (let index = snapshots.length - 1; index >= 0; index -= 1) {
|
|
1372
|
+
if (!this.reconcileRange(index, snapshots[index])) return false;
|
|
1373
|
+
}
|
|
1374
|
+
return true;
|
|
1375
|
+
}
|
|
1376
|
+
cleanup() {
|
|
1377
|
+
if (!this.active) return;
|
|
1378
|
+
this.active = false;
|
|
1379
|
+
this.unsubscribe?.();
|
|
1380
|
+
for (const instance of this.instances) {
|
|
1381
|
+
if (instance.kind === "conditional") {
|
|
1382
|
+
instance.value?.host.scope?.cleanup();
|
|
1383
|
+
} else {
|
|
1384
|
+
for (const row of instance.value.values()) row.scope?.cleanup();
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
for (const scope of this.staticScopes) scope.cleanup();
|
|
1388
|
+
this.instances.length = 0;
|
|
1389
|
+
this.staticSegments.length = 0;
|
|
1390
|
+
this.staticScopes.length = 0;
|
|
1391
|
+
this.staticValues.length = 0;
|
|
1392
|
+
}
|
|
1393
|
+
};
|
|
378
1394
|
function createHostConditionalBlockComponent(owner) {
|
|
379
1395
|
class FarmHostConditionalBlock extends React.Component {
|
|
380
1396
|
constructor() {
|
|
@@ -386,8 +1402,13 @@ function createHostConditionalBlockComponent(owner) {
|
|
|
386
1402
|
this.fallbackVersion = 0;
|
|
387
1403
|
this.propSyncQueued = false;
|
|
388
1404
|
this.currentProps = this.props;
|
|
1405
|
+
this.fallbackUnsubscribers = [];
|
|
389
1406
|
this.activeBranch = null;
|
|
390
1407
|
this.instance = null;
|
|
1408
|
+
this.requestNestedFallback = () => {
|
|
1409
|
+
this.instance?.scope?.cleanup();
|
|
1410
|
+
this.activateFallback();
|
|
1411
|
+
};
|
|
391
1412
|
this.captureRoot = (root) => {
|
|
392
1413
|
this.root = root;
|
|
393
1414
|
};
|
|
@@ -395,6 +1416,26 @@ function createHostConditionalBlockComponent(owner) {
|
|
|
395
1416
|
this.reconcile(afterCommit);
|
|
396
1417
|
};
|
|
397
1418
|
}
|
|
1419
|
+
subscribeFallbackDescendants() {
|
|
1420
|
+
for (const unsubscribe of this.fallbackUnsubscribers) unsubscribe();
|
|
1421
|
+
this.fallbackUnsubscribers = [];
|
|
1422
|
+
const ids = /* @__PURE__ */ new Set();
|
|
1423
|
+
if (this.currentProps.truthy) {
|
|
1424
|
+
collectCompilerHostBlockIds(this.currentProps.truthy.create(), ids);
|
|
1425
|
+
}
|
|
1426
|
+
if (this.currentProps.falsy) {
|
|
1427
|
+
collectCompilerHostBlockIds(this.currentProps.falsy.create(), ids);
|
|
1428
|
+
}
|
|
1429
|
+
ids.delete(this.currentProps.id);
|
|
1430
|
+
for (const id of ids) {
|
|
1431
|
+
this.fallbackUnsubscribers.push(
|
|
1432
|
+
owner.subscribe(id, (afterCommit) => {
|
|
1433
|
+
this.fallbackVersion += 1;
|
|
1434
|
+
this.forceUpdate(afterCommit);
|
|
1435
|
+
})
|
|
1436
|
+
);
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
398
1439
|
adopt() {
|
|
399
1440
|
if (!this.root) return false;
|
|
400
1441
|
const selection = hostConditionalSelection(this.currentProps);
|
|
@@ -411,11 +1452,16 @@ function createHostConditionalBlockComponent(owner) {
|
|
|
411
1452
|
const descriptor = selection.branch.create();
|
|
412
1453
|
const element = this.root.firstElementChild;
|
|
413
1454
|
if (!matchesCompilerHostElement(element, descriptor)) return false;
|
|
414
|
-
|
|
415
|
-
|
|
1455
|
+
const instance = mountCompilerHostInstance(
|
|
1456
|
+
owner,
|
|
416
1457
|
element,
|
|
417
|
-
|
|
418
|
-
|
|
1458
|
+
descriptor,
|
|
1459
|
+
selection.branch,
|
|
1460
|
+
this.requestNestedFallback
|
|
1461
|
+
);
|
|
1462
|
+
if (!instance) return false;
|
|
1463
|
+
this.activeBranch = selection.key;
|
|
1464
|
+
this.instance = instance;
|
|
419
1465
|
return true;
|
|
420
1466
|
}
|
|
421
1467
|
activateFallback(afterCommit) {
|
|
@@ -424,6 +1470,10 @@ function createHostConditionalBlockComponent(owner) {
|
|
|
424
1470
|
return;
|
|
425
1471
|
}
|
|
426
1472
|
this.fallbackRequested = true;
|
|
1473
|
+
this.instance?.scope?.cleanup();
|
|
1474
|
+
this.instance = null;
|
|
1475
|
+
this.activeBranch = null;
|
|
1476
|
+
this.subscribeFallbackDescendants();
|
|
427
1477
|
this.fallbackVersion += 1;
|
|
428
1478
|
this.setState({ fallback: true }, afterCommit);
|
|
429
1479
|
}
|
|
@@ -442,6 +1492,7 @@ function createHostConditionalBlockComponent(owner) {
|
|
|
442
1492
|
return;
|
|
443
1493
|
}
|
|
444
1494
|
if (selection.kind === "empty") {
|
|
1495
|
+
this.instance?.scope?.cleanup();
|
|
445
1496
|
if (this.instance) this.instance.element.remove();
|
|
446
1497
|
this.activeBranch = null;
|
|
447
1498
|
this.instance = null;
|
|
@@ -449,17 +1500,40 @@ function createHostConditionalBlockComponent(owner) {
|
|
|
449
1500
|
return;
|
|
450
1501
|
}
|
|
451
1502
|
if (this.activeBranch === selection.key && this.instance) {
|
|
1503
|
+
const descriptor2 = selection.branch.create();
|
|
1504
|
+
const scope = mountCompilerHostTree(
|
|
1505
|
+
owner,
|
|
1506
|
+
this.instance.element,
|
|
1507
|
+
descriptor2,
|
|
1508
|
+
this.requestNestedFallback
|
|
1509
|
+
);
|
|
1510
|
+
if (!scope) {
|
|
1511
|
+
this.activateFallback(afterCommit);
|
|
1512
|
+
return;
|
|
1513
|
+
}
|
|
1514
|
+
this.instance.scope?.cleanup();
|
|
1515
|
+
this.instance.scope = scope;
|
|
452
1516
|
applyHostConditionalBindings(selection.branch, this.instance);
|
|
453
1517
|
afterCommit?.();
|
|
454
1518
|
return;
|
|
455
1519
|
}
|
|
456
|
-
const
|
|
1520
|
+
const descriptor = selection.branch.create();
|
|
1521
|
+
const element = createCompilerHostElement(this.root.ownerDocument, descriptor);
|
|
1522
|
+
const instance = mountCompilerHostInstance(
|
|
1523
|
+
owner,
|
|
1524
|
+
element,
|
|
1525
|
+
descriptor,
|
|
1526
|
+
selection.branch,
|
|
1527
|
+
this.requestNestedFallback
|
|
1528
|
+
);
|
|
1529
|
+
if (!instance) {
|
|
1530
|
+
this.activateFallback(afterCommit);
|
|
1531
|
+
return;
|
|
1532
|
+
}
|
|
1533
|
+
this.instance?.scope?.cleanup();
|
|
457
1534
|
this.root.replaceChildren(element);
|
|
458
1535
|
this.activeBranch = selection.key;
|
|
459
|
-
this.instance =
|
|
460
|
-
element,
|
|
461
|
-
values: readHostConditionalBindingValues(selection.branch)
|
|
462
|
-
};
|
|
1536
|
+
this.instance = instance;
|
|
463
1537
|
afterCommit?.();
|
|
464
1538
|
}
|
|
465
1539
|
schedulePropSync() {
|
|
@@ -484,6 +1558,9 @@ function createHostConditionalBlockComponent(owner) {
|
|
|
484
1558
|
componentWillUnmount() {
|
|
485
1559
|
this.mounted = false;
|
|
486
1560
|
this.unsubscribe?.();
|
|
1561
|
+
for (const unsubscribe of this.fallbackUnsubscribers) unsubscribe();
|
|
1562
|
+
this.fallbackUnsubscribers = [];
|
|
1563
|
+
this.instance?.scope?.cleanup();
|
|
487
1564
|
this.root = null;
|
|
488
1565
|
this.activeBranch = null;
|
|
489
1566
|
this.instance = null;
|
|
@@ -504,6 +1581,279 @@ function createHostConditionalBlockComponent(owner) {
|
|
|
504
1581
|
FarmHostConditionalBlock.displayName = "FarmCompiledHostConditional";
|
|
505
1582
|
return FarmHostConditionalBlock;
|
|
506
1583
|
}
|
|
1584
|
+
function createConditionalRangesBlockComponent(owner) {
|
|
1585
|
+
class FarmConditionalRangesBlock extends React.Component {
|
|
1586
|
+
constructor() {
|
|
1587
|
+
super(...arguments);
|
|
1588
|
+
this.state = { fallback: false };
|
|
1589
|
+
this.root = null;
|
|
1590
|
+
this.mounted = false;
|
|
1591
|
+
this.fallbackRequested = false;
|
|
1592
|
+
this.fallbackVersion = 0;
|
|
1593
|
+
this.propFallbackQueued = false;
|
|
1594
|
+
this.currentProps = this.props;
|
|
1595
|
+
this.fallbackUnsubscribers = [];
|
|
1596
|
+
this.rangeInstances = [];
|
|
1597
|
+
this.staticSegments = [];
|
|
1598
|
+
this.staticValues = [];
|
|
1599
|
+
this.requestNestedFallback = () => {
|
|
1600
|
+
for (const instance of this.rangeInstances) instance?.host.scope?.cleanup();
|
|
1601
|
+
this.activateFallback();
|
|
1602
|
+
};
|
|
1603
|
+
this.captureRoot = (root) => {
|
|
1604
|
+
this.root = root;
|
|
1605
|
+
this.currentProps.rootRef?.(root);
|
|
1606
|
+
};
|
|
1607
|
+
this.refresh = (afterCommit) => {
|
|
1608
|
+
this.reconcile(afterCommit);
|
|
1609
|
+
};
|
|
1610
|
+
}
|
|
1611
|
+
subscribeFallbackDescendants() {
|
|
1612
|
+
for (const unsubscribe of this.fallbackUnsubscribers) unsubscribe();
|
|
1613
|
+
this.fallbackUnsubscribers = [];
|
|
1614
|
+
const ids = /* @__PURE__ */ new Set();
|
|
1615
|
+
for (const range of this.currentProps.ranges) {
|
|
1616
|
+
if (range.truthy) collectCompilerHostBlockIds(range.truthy.create(), ids);
|
|
1617
|
+
if (range.falsy) collectCompilerHostBlockIds(range.falsy.create(), ids);
|
|
1618
|
+
}
|
|
1619
|
+
ids.delete(this.currentProps.id);
|
|
1620
|
+
for (const id of ids) {
|
|
1621
|
+
this.fallbackUnsubscribers.push(
|
|
1622
|
+
owner.subscribe(id, (afterCommit) => {
|
|
1623
|
+
this.fallbackVersion += 1;
|
|
1624
|
+
this.forceUpdate(afterCommit);
|
|
1625
|
+
})
|
|
1626
|
+
);
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
readSelections(props) {
|
|
1630
|
+
const selections = [];
|
|
1631
|
+
for (const range of props.ranges) {
|
|
1632
|
+
const selection = hostConditionalSelection(range);
|
|
1633
|
+
if (selection.kind === "fallback") return null;
|
|
1634
|
+
selections.push(selection);
|
|
1635
|
+
}
|
|
1636
|
+
return selections;
|
|
1637
|
+
}
|
|
1638
|
+
adopt(props = this.currentProps) {
|
|
1639
|
+
if (!this.root || !Number.isSafeInteger(props.trailing) || props.trailing < 0) return false;
|
|
1640
|
+
const selections = this.readSelections(props);
|
|
1641
|
+
if (!selections) return false;
|
|
1642
|
+
const elements = [...this.root.children];
|
|
1643
|
+
const staticSegments = [];
|
|
1644
|
+
const instances = [];
|
|
1645
|
+
const cleanupInstances = () => {
|
|
1646
|
+
for (const instance of instances) instance?.host.scope?.cleanup();
|
|
1647
|
+
};
|
|
1648
|
+
let cursor = 0;
|
|
1649
|
+
for (let rangeIndex = 0; rangeIndex < props.ranges.length; rangeIndex += 1) {
|
|
1650
|
+
const range = props.ranges[rangeIndex];
|
|
1651
|
+
if (!Number.isSafeInteger(range.before) || range.before < 0) {
|
|
1652
|
+
cleanupInstances();
|
|
1653
|
+
return false;
|
|
1654
|
+
}
|
|
1655
|
+
const staticEnd = cursor + range.before;
|
|
1656
|
+
if (staticEnd > elements.length) {
|
|
1657
|
+
cleanupInstances();
|
|
1658
|
+
return false;
|
|
1659
|
+
}
|
|
1660
|
+
staticSegments.push(elements.slice(cursor, staticEnd));
|
|
1661
|
+
cursor = staticEnd;
|
|
1662
|
+
const selection = selections[rangeIndex];
|
|
1663
|
+
if (selection.kind === "empty") {
|
|
1664
|
+
instances.push(null);
|
|
1665
|
+
continue;
|
|
1666
|
+
}
|
|
1667
|
+
const element = elements[cursor];
|
|
1668
|
+
if (!element) {
|
|
1669
|
+
cleanupInstances();
|
|
1670
|
+
return false;
|
|
1671
|
+
}
|
|
1672
|
+
const descriptor = selection.branch.create();
|
|
1673
|
+
if (!matchesCompilerHostElement(element, descriptor)) {
|
|
1674
|
+
cleanupInstances();
|
|
1675
|
+
return false;
|
|
1676
|
+
}
|
|
1677
|
+
const host = mountCompilerHostInstance(
|
|
1678
|
+
owner,
|
|
1679
|
+
element,
|
|
1680
|
+
descriptor,
|
|
1681
|
+
selection.branch,
|
|
1682
|
+
this.requestNestedFallback
|
|
1683
|
+
);
|
|
1684
|
+
if (!host) {
|
|
1685
|
+
cleanupInstances();
|
|
1686
|
+
return false;
|
|
1687
|
+
}
|
|
1688
|
+
instances.push({
|
|
1689
|
+
key: selection.key,
|
|
1690
|
+
host
|
|
1691
|
+
});
|
|
1692
|
+
cursor += 1;
|
|
1693
|
+
}
|
|
1694
|
+
if (cursor + props.trailing !== elements.length) {
|
|
1695
|
+
cleanupInstances();
|
|
1696
|
+
return false;
|
|
1697
|
+
}
|
|
1698
|
+
staticSegments.push(elements.slice(cursor));
|
|
1699
|
+
this.staticSegments = staticSegments;
|
|
1700
|
+
this.rangeInstances = instances;
|
|
1701
|
+
if (!applyStaticRangeBindings(props.bindings, this.staticSegments, this.staticValues)) {
|
|
1702
|
+
cleanupInstances();
|
|
1703
|
+
this.rangeInstances = [];
|
|
1704
|
+
this.staticSegments = [];
|
|
1705
|
+
return false;
|
|
1706
|
+
}
|
|
1707
|
+
return true;
|
|
1708
|
+
}
|
|
1709
|
+
anchorAfter(rangeIndex) {
|
|
1710
|
+
for (let next = rangeIndex + 1; next < this.rangeInstances.length; next += 1) {
|
|
1711
|
+
const staticAnchor = this.staticSegments[next]?.[0];
|
|
1712
|
+
if (staticAnchor) return staticAnchor;
|
|
1713
|
+
const rangeAnchor = this.rangeInstances[next]?.host.element;
|
|
1714
|
+
if (rangeAnchor) return rangeAnchor;
|
|
1715
|
+
}
|
|
1716
|
+
return this.staticSegments[this.rangeInstances.length]?.[0] || null;
|
|
1717
|
+
}
|
|
1718
|
+
reconcileRange(rangeIndex, selection) {
|
|
1719
|
+
if (!this.root) return false;
|
|
1720
|
+
const previous = this.rangeInstances[rangeIndex];
|
|
1721
|
+
if (selection.kind === "empty") {
|
|
1722
|
+
previous?.host.scope?.cleanup();
|
|
1723
|
+
previous?.host.element.remove();
|
|
1724
|
+
this.rangeInstances[rangeIndex] = null;
|
|
1725
|
+
return true;
|
|
1726
|
+
}
|
|
1727
|
+
if (previous?.key === selection.key) {
|
|
1728
|
+
const descriptor2 = selection.branch.create();
|
|
1729
|
+
const scope = mountCompilerHostTree(
|
|
1730
|
+
owner,
|
|
1731
|
+
previous.host.element,
|
|
1732
|
+
descriptor2,
|
|
1733
|
+
this.requestNestedFallback
|
|
1734
|
+
);
|
|
1735
|
+
if (!scope) {
|
|
1736
|
+
this.requestNestedFallback();
|
|
1737
|
+
return false;
|
|
1738
|
+
}
|
|
1739
|
+
previous.host.scope?.cleanup();
|
|
1740
|
+
previous.host.scope = scope;
|
|
1741
|
+
applyHostConditionalBindings(selection.branch, previous.host);
|
|
1742
|
+
return true;
|
|
1743
|
+
}
|
|
1744
|
+
const descriptor = selection.branch.create();
|
|
1745
|
+
const element = createCompilerHostElement(this.root.ownerDocument, descriptor);
|
|
1746
|
+
const host = mountCompilerHostInstance(
|
|
1747
|
+
owner,
|
|
1748
|
+
element,
|
|
1749
|
+
descriptor,
|
|
1750
|
+
selection.branch,
|
|
1751
|
+
this.requestNestedFallback
|
|
1752
|
+
);
|
|
1753
|
+
if (!host) {
|
|
1754
|
+
this.requestNestedFallback();
|
|
1755
|
+
return false;
|
|
1756
|
+
}
|
|
1757
|
+
previous?.host.scope?.cleanup();
|
|
1758
|
+
if (previous) previous.host.element.replaceWith(element);
|
|
1759
|
+
else this.root.insertBefore(element, this.anchorAfter(rangeIndex));
|
|
1760
|
+
this.rangeInstances[rangeIndex] = {
|
|
1761
|
+
key: selection.key,
|
|
1762
|
+
host
|
|
1763
|
+
};
|
|
1764
|
+
return true;
|
|
1765
|
+
}
|
|
1766
|
+
reconcile(afterCommit) {
|
|
1767
|
+
if (!this.mounted || !this.root) {
|
|
1768
|
+
afterCommit?.();
|
|
1769
|
+
return;
|
|
1770
|
+
}
|
|
1771
|
+
if (this.state.fallback) {
|
|
1772
|
+
this.fallbackVersion += 1;
|
|
1773
|
+
this.forceUpdate(afterCommit);
|
|
1774
|
+
return;
|
|
1775
|
+
}
|
|
1776
|
+
if (this.currentProps.ranges.length !== this.rangeInstances.length) {
|
|
1777
|
+
this.activateFallback(afterCommit);
|
|
1778
|
+
return;
|
|
1779
|
+
}
|
|
1780
|
+
const selections = this.readSelections(this.currentProps);
|
|
1781
|
+
if (!selections) {
|
|
1782
|
+
this.activateFallback(afterCommit);
|
|
1783
|
+
return;
|
|
1784
|
+
}
|
|
1785
|
+
if (!applyStaticRangeBindings(
|
|
1786
|
+
this.currentProps.bindings,
|
|
1787
|
+
this.staticSegments,
|
|
1788
|
+
this.staticValues
|
|
1789
|
+
)) {
|
|
1790
|
+
this.activateFallback(afterCommit);
|
|
1791
|
+
return;
|
|
1792
|
+
}
|
|
1793
|
+
for (let rangeIndex = this.rangeInstances.length - 1; rangeIndex >= 0; rangeIndex -= 1) {
|
|
1794
|
+
if (!this.reconcileRange(rangeIndex, selections[rangeIndex])) {
|
|
1795
|
+
afterCommit?.();
|
|
1796
|
+
return;
|
|
1797
|
+
}
|
|
1798
|
+
}
|
|
1799
|
+
afterCommit?.();
|
|
1800
|
+
}
|
|
1801
|
+
activateFallback(afterCommit) {
|
|
1802
|
+
if (!this.mounted || this.state.fallback || this.fallbackRequested) {
|
|
1803
|
+
afterCommit?.();
|
|
1804
|
+
return;
|
|
1805
|
+
}
|
|
1806
|
+
this.fallbackRequested = true;
|
|
1807
|
+
for (const instance of this.rangeInstances) instance?.host.scope?.cleanup();
|
|
1808
|
+
this.subscribeFallbackDescendants();
|
|
1809
|
+
this.setState({ fallback: true }, afterCommit);
|
|
1810
|
+
}
|
|
1811
|
+
schedulePropFallback() {
|
|
1812
|
+
if (this.propFallbackQueued) return;
|
|
1813
|
+
this.propFallbackQueued = true;
|
|
1814
|
+
queueMicrotask(() => {
|
|
1815
|
+
this.propFallbackQueued = false;
|
|
1816
|
+
if (this.mounted && !this.state.fallback) this.activateFallback();
|
|
1817
|
+
});
|
|
1818
|
+
}
|
|
1819
|
+
shouldComponentUpdate(nextProps, nextState) {
|
|
1820
|
+
this.currentProps = nextProps;
|
|
1821
|
+
if (nextState.fallback || this.state.fallback) return true;
|
|
1822
|
+
this.schedulePropFallback();
|
|
1823
|
+
return false;
|
|
1824
|
+
}
|
|
1825
|
+
componentDidMount() {
|
|
1826
|
+
this.mounted = true;
|
|
1827
|
+
this.unsubscribe = owner.subscribe(this.props.id, this.refresh);
|
|
1828
|
+
if (!this.adopt()) this.activateFallback();
|
|
1829
|
+
}
|
|
1830
|
+
componentWillUnmount() {
|
|
1831
|
+
this.mounted = false;
|
|
1832
|
+
this.unsubscribe?.();
|
|
1833
|
+
for (const unsubscribe of this.fallbackUnsubscribers) unsubscribe();
|
|
1834
|
+
this.fallbackUnsubscribers = [];
|
|
1835
|
+
for (const instance of this.rangeInstances) instance?.host.scope?.cleanup();
|
|
1836
|
+
this.root = null;
|
|
1837
|
+
this.rangeInstances = [];
|
|
1838
|
+
this.staticSegments = [];
|
|
1839
|
+
this.staticValues.length = 0;
|
|
1840
|
+
}
|
|
1841
|
+
render() {
|
|
1842
|
+
const container = this.currentProps.render();
|
|
1843
|
+
if (!React.isValidElement(container) || typeof container.type !== "string") {
|
|
1844
|
+
throw new TypeError(
|
|
1845
|
+
`Compiled conditional ranges ${this.currentProps.id} must own one host container.`
|
|
1846
|
+
);
|
|
1847
|
+
}
|
|
1848
|
+
return React.cloneElement(container, {
|
|
1849
|
+
key: this.state.fallback ? `react-${this.fallbackVersion}` : "compiled",
|
|
1850
|
+
ref: this.captureRoot
|
|
1851
|
+
});
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1854
|
+
FarmConditionalRangesBlock.displayName = "FarmCompiledConditionalRanges";
|
|
1855
|
+
return FarmConditionalRangesBlock;
|
|
1856
|
+
}
|
|
507
1857
|
function longestIncreasingSubsequencePositions(sequence) {
|
|
508
1858
|
const tails = [];
|
|
509
1859
|
const previous = Array.from({ length: sequence.length }, () => -1);
|
|
@@ -528,6 +1878,10 @@ function longestIncreasingSubsequencePositions(sequence) {
|
|
|
528
1878
|
return positions;
|
|
529
1879
|
}
|
|
530
1880
|
function createKeyedRowsBlockComponent(owner) {
|
|
1881
|
+
const rowHostScopeOwner = {
|
|
1882
|
+
subscribe: () => () => {
|
|
1883
|
+
}
|
|
1884
|
+
};
|
|
531
1885
|
class FarmKeyedRowConditional extends React.Component {
|
|
532
1886
|
constructor() {
|
|
533
1887
|
super(...arguments);
|
|
@@ -584,16 +1938,23 @@ function createKeyedRowsBlockComponent(owner) {
|
|
|
584
1938
|
this.renderVersion = 0;
|
|
585
1939
|
this.eventHandlers = /* @__PURE__ */ new Map();
|
|
586
1940
|
this.conditionalListeners = /* @__PURE__ */ new Map();
|
|
1941
|
+
this.instancesByElement = /* @__PURE__ */ new WeakMap();
|
|
587
1942
|
this.conditionalOwner = {
|
|
588
1943
|
subscribe: (key, id, refresh) => this.subscribeToRowConditional(key, id, refresh)
|
|
589
1944
|
};
|
|
590
1945
|
this.captureRoot = (root) => {
|
|
591
1946
|
this.root = root;
|
|
592
1947
|
};
|
|
1948
|
+
this.requestHostScopeFallback = () => {
|
|
1949
|
+
this.activateFallback();
|
|
1950
|
+
};
|
|
593
1951
|
this.rowEvent = (item, index, eventId) => {
|
|
594
1952
|
if (this.state.fallback) {
|
|
595
1953
|
return (event) => this.currentProps.events?.[eventId]?.invoke(item, index, event);
|
|
596
1954
|
}
|
|
1955
|
+
if (this.usesDelegatedEvents()) {
|
|
1956
|
+
return void 0;
|
|
1957
|
+
}
|
|
597
1958
|
const key = keyedRowIdentity(this.currentProps.rowKey(item, index));
|
|
598
1959
|
let handlers = this.eventHandlers.get(key);
|
|
599
1960
|
if (!handlers) {
|
|
@@ -611,6 +1972,26 @@ function createKeyedRowsBlockComponent(owner) {
|
|
|
611
1972
|
handlers.set(eventId, handler);
|
|
612
1973
|
return handler;
|
|
613
1974
|
};
|
|
1975
|
+
this.dispatchDelegatedEvent = (name, event) => {
|
|
1976
|
+
const instance = this.eventRowInstance(event);
|
|
1977
|
+
const eventTarget = event.target;
|
|
1978
|
+
if (!instance || !eventTarget) return;
|
|
1979
|
+
const capture = name.endsWith("Capture");
|
|
1980
|
+
const matches = (this.currentProps.events || []).filter((descriptor) => descriptor.name === name && descriptor.path !== void 0).map((descriptor) => ({
|
|
1981
|
+
descriptor,
|
|
1982
|
+
target: findCompilerHostTarget(instance.element, descriptor.path || [])
|
|
1983
|
+
})).filter(
|
|
1984
|
+
(match) => Boolean(
|
|
1985
|
+
match.target && (match.target === eventTarget || match.target.contains(eventTarget))
|
|
1986
|
+
)
|
|
1987
|
+
).sort(
|
|
1988
|
+
(left, right) => capture ? (left.descriptor.path?.length || 0) - (right.descriptor.path?.length || 0) : (right.descriptor.path?.length || 0) - (left.descriptor.path?.length || 0)
|
|
1989
|
+
);
|
|
1990
|
+
for (const match of matches) {
|
|
1991
|
+
this.invokeDelegatedEvent(match.descriptor, instance, event, match.target);
|
|
1992
|
+
if (event.isPropagationStopped()) break;
|
|
1993
|
+
}
|
|
1994
|
+
};
|
|
614
1995
|
this.rowConditional = (item, index, conditionalId, render) => {
|
|
615
1996
|
if (this.state.fallback) return render(item, index);
|
|
616
1997
|
const key = keyedRowIdentity(this.currentProps.rowKey(item, index));
|
|
@@ -625,17 +2006,65 @@ function createKeyedRowsBlockComponent(owner) {
|
|
|
625
2006
|
render
|
|
626
2007
|
});
|
|
627
2008
|
};
|
|
628
|
-
this.refresh = (afterCommit) => {
|
|
2009
|
+
this.refresh = (afterCommit, dirtyState) => {
|
|
2010
|
+
if (dirtyState && this.refreshDirtyBindings(dirtyState, afterCommit)) return;
|
|
629
2011
|
this.reconcile(afterCommit);
|
|
630
2012
|
};
|
|
631
2013
|
}
|
|
632
2014
|
readRows(props) {
|
|
633
|
-
const
|
|
634
|
-
const items = source ? Array.from(source) : [];
|
|
2015
|
+
const items = materializeIterable(props.items());
|
|
635
2016
|
const keys = items.map((item, index) => keyedRowIdentity(props.rowKey(item, index)));
|
|
636
2017
|
if (new Set(keys).size !== keys.length) return null;
|
|
637
2018
|
return { items, keys };
|
|
638
2019
|
}
|
|
2020
|
+
usesDelegatedEvents(props = this.currentProps) {
|
|
2021
|
+
return Boolean(
|
|
2022
|
+
props.delegateEvents && props.events?.length && props.events.every((event) => event.path !== void 0)
|
|
2023
|
+
);
|
|
2024
|
+
}
|
|
2025
|
+
rebuildElementIndex(instances) {
|
|
2026
|
+
this.instancesByElement = /* @__PURE__ */ new WeakMap();
|
|
2027
|
+
for (const instance of instances.values()) {
|
|
2028
|
+
this.instancesByElement.set(instance.element, instance);
|
|
2029
|
+
}
|
|
2030
|
+
}
|
|
2031
|
+
eventRowInstance(event) {
|
|
2032
|
+
if (!this.root) return void 0;
|
|
2033
|
+
const target = event.target;
|
|
2034
|
+
if (!target) return void 0;
|
|
2035
|
+
let element = target.nodeType === 1 ? target : target.parentElement;
|
|
2036
|
+
while (element && element.parentElement !== this.root) element = element.parentElement;
|
|
2037
|
+
return element?.parentElement === this.root ? this.instancesByElement.get(element) : void 0;
|
|
2038
|
+
}
|
|
2039
|
+
invokeDelegatedEvent(descriptor, instance, event, currentTarget) {
|
|
2040
|
+
const ownCurrentTarget = Object.getOwnPropertyDescriptor(event, "currentTarget");
|
|
2041
|
+
try {
|
|
2042
|
+
Object.defineProperty(event, "currentTarget", {
|
|
2043
|
+
configurable: true,
|
|
2044
|
+
value: currentTarget
|
|
2045
|
+
});
|
|
2046
|
+
descriptor.invoke(instance.item, instance.index, event);
|
|
2047
|
+
} finally {
|
|
2048
|
+
if (ownCurrentTarget) Object.defineProperty(event, "currentTarget", ownCurrentTarget);
|
|
2049
|
+
else Reflect.deleteProperty(event, "currentTarget");
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
2052
|
+
delegatedContainerProps(container) {
|
|
2053
|
+
if (this.state.fallback || !this.usesDelegatedEvents()) return {};
|
|
2054
|
+
const props = container.props;
|
|
2055
|
+
return Object.fromEntries(
|
|
2056
|
+
[...new Set((this.currentProps.events || []).map((event) => event.name))].map((name) => {
|
|
2057
|
+
const existing = props[name];
|
|
2058
|
+
const capture = name.endsWith("Capture");
|
|
2059
|
+
const handler = (event) => {
|
|
2060
|
+
if (capture) existing?.(event);
|
|
2061
|
+
if (!event.isPropagationStopped()) this.dispatchDelegatedEvent(name, event);
|
|
2062
|
+
if (!capture && !event.isPropagationStopped()) existing?.(event);
|
|
2063
|
+
};
|
|
2064
|
+
return [name, handler];
|
|
2065
|
+
})
|
|
2066
|
+
);
|
|
2067
|
+
}
|
|
639
2068
|
subscribeToRowConditional(key, id, refresh) {
|
|
640
2069
|
let listeners = this.conditionalListeners.get(key);
|
|
641
2070
|
if (!listeners) {
|
|
@@ -651,7 +2080,21 @@ function createKeyedRowsBlockComponent(owner) {
|
|
|
651
2080
|
};
|
|
652
2081
|
}
|
|
653
2082
|
hasReactOwnedRows(props = this.currentProps) {
|
|
654
|
-
return Boolean(
|
|
2083
|
+
return Boolean(
|
|
2084
|
+
props.conditionals?.length || props.events?.length && !this.usesDelegatedEvents(props)
|
|
2085
|
+
);
|
|
2086
|
+
}
|
|
2087
|
+
cleanupHostScopes(instances = this.instances) {
|
|
2088
|
+
for (const instance of instances.values()) instance.scope?.cleanup();
|
|
2089
|
+
}
|
|
2090
|
+
mountRowHostScope(element, descriptor, props = this.currentProps) {
|
|
2091
|
+
if (!props.hostBlocks) return void 0;
|
|
2092
|
+
return mountCompilerHostTree(
|
|
2093
|
+
rowHostScopeOwner,
|
|
2094
|
+
element,
|
|
2095
|
+
descriptor,
|
|
2096
|
+
this.requestHostScopeFallback
|
|
2097
|
+
);
|
|
655
2098
|
}
|
|
656
2099
|
pruneEventHandlers(keys) {
|
|
657
2100
|
const active = new Set(keys);
|
|
@@ -675,16 +2118,20 @@ function createKeyedRowsBlockComponent(owner) {
|
|
|
675
2118
|
);
|
|
676
2119
|
const instances = /* @__PURE__ */ new Map();
|
|
677
2120
|
for (let index = 0; index < rows.items.length; index += 1) {
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
this.
|
|
681
|
-
|
|
682
|
-
|
|
2121
|
+
const descriptor = this.currentProps.create(rows.items[index], index);
|
|
2122
|
+
if (this.hasReactOwnedRows() && !matchesCompilerHostElement(elements[index], descriptor, opaqueConditionalPaths)) {
|
|
2123
|
+
this.cleanupHostScopes(instances);
|
|
2124
|
+
return false;
|
|
2125
|
+
}
|
|
2126
|
+
const scope = this.mountRowHostScope(elements[index], descriptor);
|
|
2127
|
+
if (this.currentProps.hostBlocks && !scope) {
|
|
2128
|
+
this.cleanupHostScopes(instances);
|
|
683
2129
|
return false;
|
|
684
2130
|
}
|
|
685
2131
|
const instance = {
|
|
686
2132
|
key: rows.keys[index],
|
|
687
2133
|
element: elements[index],
|
|
2134
|
+
scope: scope || void 0,
|
|
688
2135
|
values: this.hasReactOwnedRows() ? this.currentProps.bindings.map(() => UNSET_KEYED_ROW_BINDING) : readKeyedRowBindingValues(this.currentProps, rows.items[index], index),
|
|
689
2136
|
item: rows.items[index],
|
|
690
2137
|
index,
|
|
@@ -699,7 +2146,9 @@ function createKeyedRowsBlockComponent(owner) {
|
|
|
699
2146
|
}
|
|
700
2147
|
instances.set(rows.keys[index], instance);
|
|
701
2148
|
}
|
|
2149
|
+
this.cleanupHostScopes();
|
|
702
2150
|
this.instances = instances;
|
|
2151
|
+
this.rebuildElementIndex(instances);
|
|
703
2152
|
this.pruneEventHandlers(rows.keys);
|
|
704
2153
|
this.pruneConditionalListeners(rows.keys);
|
|
705
2154
|
return true;
|
|
@@ -718,6 +2167,7 @@ function createKeyedRowsBlockComponent(owner) {
|
|
|
718
2167
|
}
|
|
719
2168
|
this.fallbackRequested = true;
|
|
720
2169
|
this.fallbackKeysWereUnsafe = this.hasUnsafeFallbackKeys();
|
|
2170
|
+
this.cleanupHostScopes();
|
|
721
2171
|
this.fallbackVersion += 1;
|
|
722
2172
|
this.setState({ fallback: true }, afterCommit);
|
|
723
2173
|
}
|
|
@@ -752,6 +2202,116 @@ function createKeyedRowsBlockComponent(owner) {
|
|
|
752
2202
|
}
|
|
753
2203
|
});
|
|
754
2204
|
}
|
|
2205
|
+
refreshDirtyBindings(dirtyState, afterCommit) {
|
|
2206
|
+
if (!this.mounted || !this.root || this.state.fallback || this.hasReactOwnedRows() || this.currentProps.hostBlocks || !this.currentProps.structureDependencies || this.currentProps.structureDependencies.some((dependency) => dirtyState.has(dependency)) || this.currentProps.bindings.some((binding) => binding.dependencies === void 0)) {
|
|
2207
|
+
return false;
|
|
2208
|
+
}
|
|
2209
|
+
const affectedBindingIndices = [];
|
|
2210
|
+
for (let bindingIndex = 0; bindingIndex < this.currentProps.bindings.length; bindingIndex += 1) {
|
|
2211
|
+
const dependencies = this.currentProps.bindings[bindingIndex].dependencies || [];
|
|
2212
|
+
if (dependencies.some((dependency) => dirtyState.has(dependency))) {
|
|
2213
|
+
affectedBindingIndices.push(bindingIndex);
|
|
2214
|
+
}
|
|
2215
|
+
}
|
|
2216
|
+
for (const instance of this.instances.values()) {
|
|
2217
|
+
for (const bindingIndex of affectedBindingIndices) {
|
|
2218
|
+
applyKeyedRowBinding(
|
|
2219
|
+
this.currentProps,
|
|
2220
|
+
instance,
|
|
2221
|
+
instance.item,
|
|
2222
|
+
instance.index,
|
|
2223
|
+
bindingIndex
|
|
2224
|
+
);
|
|
2225
|
+
}
|
|
2226
|
+
}
|
|
2227
|
+
afterCommit?.();
|
|
2228
|
+
return true;
|
|
2229
|
+
}
|
|
2230
|
+
reconcileStableRows(rows, afterCommit) {
|
|
2231
|
+
if (rows.keys.length !== this.instances.size) return false;
|
|
2232
|
+
let index = 0;
|
|
2233
|
+
for (const key of this.instances.keys()) {
|
|
2234
|
+
if (rows.keys[index] !== key) return false;
|
|
2235
|
+
index += 1;
|
|
2236
|
+
}
|
|
2237
|
+
const conditionalChanges = [];
|
|
2238
|
+
for (index = 0; index < rows.items.length; index += 1) {
|
|
2239
|
+
const key = rows.keys[index];
|
|
2240
|
+
const existing = this.instances.get(key);
|
|
2241
|
+
if (!existing) return false;
|
|
2242
|
+
if (this.currentProps.hostBlocks) {
|
|
2243
|
+
const descriptor = this.currentProps.create(rows.items[index], index);
|
|
2244
|
+
if (!existing.scope?.update(descriptor)) {
|
|
2245
|
+
this.activateFallback(afterCommit);
|
|
2246
|
+
return true;
|
|
2247
|
+
}
|
|
2248
|
+
}
|
|
2249
|
+
applyKeyedRowBindings(this.currentProps, existing, rows.items[index], index);
|
|
2250
|
+
const conditionalValues = readKeyedRowConditionalValues(
|
|
2251
|
+
this.currentProps,
|
|
2252
|
+
rows.items[index],
|
|
2253
|
+
index
|
|
2254
|
+
);
|
|
2255
|
+
for (const [id, values] of conditionalValues) {
|
|
2256
|
+
if (keyedRowConditionalChanged(existing.conditionalValues.get(id), values)) {
|
|
2257
|
+
conditionalChanges.push({ key, id, item: rows.items[index], index });
|
|
2258
|
+
}
|
|
2259
|
+
}
|
|
2260
|
+
existing.conditionalValues = conditionalValues;
|
|
2261
|
+
existing.item = rows.items[index];
|
|
2262
|
+
existing.index = index;
|
|
2263
|
+
}
|
|
2264
|
+
this.notifyConditionalChanges(conditionalChanges, afterCommit);
|
|
2265
|
+
return true;
|
|
2266
|
+
}
|
|
2267
|
+
reconcileSingleRemoval(rows, afterCommit) {
|
|
2268
|
+
if (this.hasReactOwnedRows() || rows.keys.length + 1 !== this.instances.size) return false;
|
|
2269
|
+
const previousKeys = [...this.instances.keys()];
|
|
2270
|
+
let removedIndex = 0;
|
|
2271
|
+
while (removedIndex < rows.keys.length && previousKeys[removedIndex] === rows.keys[removedIndex]) {
|
|
2272
|
+
removedIndex += 1;
|
|
2273
|
+
}
|
|
2274
|
+
for (let index = removedIndex; index < rows.keys.length; index += 1) {
|
|
2275
|
+
if (previousKeys[index + 1] !== rows.keys[index]) return false;
|
|
2276
|
+
}
|
|
2277
|
+
const removedKey = previousKeys[removedIndex];
|
|
2278
|
+
const removed = this.instances.get(removedKey);
|
|
2279
|
+
if (!removed) return false;
|
|
2280
|
+
const conditionalChanges = [];
|
|
2281
|
+
for (let index = 0; index < rows.items.length; index += 1) {
|
|
2282
|
+
const key = rows.keys[index];
|
|
2283
|
+
const existing = this.instances.get(key);
|
|
2284
|
+
if (!existing) return false;
|
|
2285
|
+
if (this.currentProps.hostBlocks) {
|
|
2286
|
+
const descriptor = this.currentProps.create(rows.items[index], index);
|
|
2287
|
+
if (!existing.scope?.update(descriptor)) {
|
|
2288
|
+
this.activateFallback(afterCommit);
|
|
2289
|
+
return true;
|
|
2290
|
+
}
|
|
2291
|
+
}
|
|
2292
|
+
applyKeyedRowBindings(this.currentProps, existing, rows.items[index], index);
|
|
2293
|
+
const conditionalValues = readKeyedRowConditionalValues(
|
|
2294
|
+
this.currentProps,
|
|
2295
|
+
rows.items[index],
|
|
2296
|
+
index
|
|
2297
|
+
);
|
|
2298
|
+
for (const [id, values] of conditionalValues) {
|
|
2299
|
+
if (keyedRowConditionalChanged(existing.conditionalValues.get(id), values)) {
|
|
2300
|
+
conditionalChanges.push({ key, id, item: rows.items[index], index });
|
|
2301
|
+
}
|
|
2302
|
+
}
|
|
2303
|
+
existing.conditionalValues = conditionalValues;
|
|
2304
|
+
existing.item = rows.items[index];
|
|
2305
|
+
existing.index = index;
|
|
2306
|
+
}
|
|
2307
|
+
removed.scope?.cleanup();
|
|
2308
|
+
removed.element.remove();
|
|
2309
|
+
this.instances.delete(removedKey);
|
|
2310
|
+
this.eventHandlers.delete(removedKey);
|
|
2311
|
+
this.conditionalListeners.delete(removedKey);
|
|
2312
|
+
this.notifyConditionalChanges(conditionalChanges, afterCommit);
|
|
2313
|
+
return true;
|
|
2314
|
+
}
|
|
755
2315
|
reconcile(afterCommit) {
|
|
756
2316
|
if (!this.mounted || !this.root) {
|
|
757
2317
|
afterCommit?.();
|
|
@@ -771,27 +2331,54 @@ function createKeyedRowsBlockComponent(owner) {
|
|
|
771
2331
|
this.activateFallback(afterCommit);
|
|
772
2332
|
return;
|
|
773
2333
|
}
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
2334
|
+
if (this.hasReactOwnedRows()) {
|
|
2335
|
+
const previousKeys = [...this.instances.keys()];
|
|
2336
|
+
if (rows.keys.length !== previousKeys.length || rows.keys.some((key, index) => key !== previousKeys[index])) {
|
|
2337
|
+
this.synchronizeReactOwnedRows(afterCommit);
|
|
2338
|
+
return;
|
|
2339
|
+
}
|
|
2340
|
+
}
|
|
2341
|
+
if (rows.items.length === 0) {
|
|
2342
|
+
this.cleanupHostScopes();
|
|
2343
|
+
this.root.replaceChildren();
|
|
2344
|
+
this.instances = /* @__PURE__ */ new Map();
|
|
2345
|
+
this.instancesByElement = /* @__PURE__ */ new WeakMap();
|
|
2346
|
+
this.eventHandlers.clear();
|
|
2347
|
+
this.conditionalListeners.clear();
|
|
2348
|
+
afterCommit?.();
|
|
777
2349
|
return;
|
|
778
2350
|
}
|
|
779
|
-
|
|
2351
|
+
if (this.reconcileStableRows(rows, afterCommit)) return;
|
|
2352
|
+
if (this.reconcileSingleRemoval(rows, afterCommit)) return;
|
|
780
2353
|
const activeElement = this.root.ownerDocument.activeElement;
|
|
781
2354
|
const restoreFocus = Boolean(activeElement && this.root.contains(activeElement));
|
|
782
|
-
[...this.instances].forEach(([key], index) => oldIndices.set(key, index));
|
|
783
2355
|
const nextKeys = new Set(rows.keys);
|
|
2356
|
+
const hasSurvivingRows = rows.keys.some((key) => this.instances.has(key));
|
|
2357
|
+
const oldIndices = /* @__PURE__ */ new Map();
|
|
2358
|
+
if (hasSurvivingRows) {
|
|
2359
|
+
[...this.instances].forEach(([key], index) => oldIndices.set(key, index));
|
|
2360
|
+
}
|
|
784
2361
|
for (const [key, instance] of this.instances) {
|
|
785
|
-
if (!nextKeys.has(key))
|
|
2362
|
+
if (!nextKeys.has(key)) {
|
|
2363
|
+
instance.scope?.cleanup();
|
|
2364
|
+
if (hasSurvivingRows) instance.element.remove();
|
|
2365
|
+
}
|
|
786
2366
|
}
|
|
787
|
-
const sequence = rows.keys.map((key) => oldIndices.get(key) ?? -1);
|
|
788
|
-
const stablePositions = longestIncreasingSubsequencePositions(sequence);
|
|
2367
|
+
const sequence = hasSurvivingRows ? rows.keys.map((key) => oldIndices.get(key) ?? -1) : rows.keys.map(() => -1);
|
|
2368
|
+
const stablePositions = hasSurvivingRows ? longestIncreasingSubsequencePositions(sequence) : /* @__PURE__ */ new Set();
|
|
789
2369
|
const nextInstances = [];
|
|
790
2370
|
const conditionalChanges = [];
|
|
791
2371
|
for (let index = 0; index < rows.items.length; index += 1) {
|
|
792
2372
|
const key = rows.keys[index];
|
|
793
2373
|
const existing = this.instances.get(key);
|
|
794
2374
|
if (existing) {
|
|
2375
|
+
if (this.currentProps.hostBlocks) {
|
|
2376
|
+
const descriptor2 = this.currentProps.create(rows.items[index], index);
|
|
2377
|
+
if (!existing.scope?.update(descriptor2)) {
|
|
2378
|
+
this.activateFallback(afterCommit);
|
|
2379
|
+
return;
|
|
2380
|
+
}
|
|
2381
|
+
}
|
|
795
2382
|
applyKeyedRowBindings(this.currentProps, existing, rows.items[index], index);
|
|
796
2383
|
const conditionalValues = readKeyedRowConditionalValues(
|
|
797
2384
|
this.currentProps,
|
|
@@ -809,13 +2396,20 @@ function createKeyedRowsBlockComponent(owner) {
|
|
|
809
2396
|
nextInstances.push(existing);
|
|
810
2397
|
continue;
|
|
811
2398
|
}
|
|
812
|
-
const
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
)
|
|
2399
|
+
const descriptor = this.currentProps.create(rows.items[index], index);
|
|
2400
|
+
const element = createCompilerHostElement(this.root.ownerDocument, descriptor);
|
|
2401
|
+
const scope = this.mountRowHostScope(element, descriptor);
|
|
2402
|
+
if (this.currentProps.hostBlocks && !scope) {
|
|
2403
|
+
for (const instance of nextInstances) {
|
|
2404
|
+
if (!this.instances.has(instance.key)) instance.scope?.cleanup();
|
|
2405
|
+
}
|
|
2406
|
+
this.activateFallback(afterCommit);
|
|
2407
|
+
return;
|
|
2408
|
+
}
|
|
816
2409
|
nextInstances.push({
|
|
817
2410
|
key,
|
|
818
2411
|
element,
|
|
2412
|
+
scope: scope || void 0,
|
|
819
2413
|
values: readKeyedRowBindingValues(this.currentProps, rows.items[index], index),
|
|
820
2414
|
item: rows.items[index],
|
|
821
2415
|
index,
|
|
@@ -826,17 +2420,34 @@ function createKeyedRowsBlockComponent(owner) {
|
|
|
826
2420
|
)
|
|
827
2421
|
});
|
|
828
2422
|
}
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
const instance
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
2423
|
+
if (!hasSurvivingRows) {
|
|
2424
|
+
const fragment = this.root.ownerDocument.createDocumentFragment();
|
|
2425
|
+
for (const instance of nextInstances) fragment.append(instance.element);
|
|
2426
|
+
this.root.replaceChildren(fragment);
|
|
2427
|
+
} else {
|
|
2428
|
+
let anchor = null;
|
|
2429
|
+
for (let index = nextInstances.length - 1; index >= 0; index -= 1) {
|
|
2430
|
+
const instance = nextInstances[index];
|
|
2431
|
+
if (sequence[index] < 0) {
|
|
2432
|
+
let start = index;
|
|
2433
|
+
while (start > 0 && sequence[start - 1] < 0) start -= 1;
|
|
2434
|
+
const fragment = this.root.ownerDocument.createDocumentFragment();
|
|
2435
|
+
for (let itemIndex = start; itemIndex <= index; itemIndex += 1) {
|
|
2436
|
+
fragment.append(nextInstances[itemIndex].element);
|
|
2437
|
+
}
|
|
2438
|
+
this.root.insertBefore(fragment, anchor);
|
|
2439
|
+
anchor = nextInstances[start].element;
|
|
2440
|
+
index = start;
|
|
2441
|
+
} else {
|
|
2442
|
+
if (!stablePositions.has(index) && instance.element.nextSibling !== anchor) {
|
|
2443
|
+
this.root.insertBefore(instance.element, anchor);
|
|
2444
|
+
}
|
|
2445
|
+
anchor = instance.element;
|
|
2446
|
+
}
|
|
836
2447
|
}
|
|
837
|
-
anchor = instance.element;
|
|
838
2448
|
}
|
|
839
2449
|
this.instances = new Map(nextInstances.map((instance) => [instance.key, instance]));
|
|
2450
|
+
this.rebuildElementIndex(this.instances);
|
|
840
2451
|
this.pruneEventHandlers(rows.keys);
|
|
841
2452
|
this.pruneConditionalListeners(rows.keys);
|
|
842
2453
|
if (restoreFocus && activeElement?.isConnected && activeElement.ownerDocument.activeElement !== activeElement && "focus" in activeElement) {
|
|
@@ -879,7 +2490,9 @@ function createKeyedRowsBlockComponent(owner) {
|
|
|
879
2490
|
this.mounted = false;
|
|
880
2491
|
this.unsubscribe?.();
|
|
881
2492
|
this.root = null;
|
|
2493
|
+
this.cleanupHostScopes();
|
|
882
2494
|
this.instances.clear();
|
|
2495
|
+
this.instancesByElement = /* @__PURE__ */ new WeakMap();
|
|
883
2496
|
this.eventHandlers.clear();
|
|
884
2497
|
this.conditionalListeners.clear();
|
|
885
2498
|
}
|
|
@@ -892,6 +2505,7 @@ function createKeyedRowsBlockComponent(owner) {
|
|
|
892
2505
|
);
|
|
893
2506
|
}
|
|
894
2507
|
return React.cloneElement(container, {
|
|
2508
|
+
...this.delegatedContainerProps(container),
|
|
895
2509
|
key: this.state.fallback ? `react-${this.fallbackVersion}` : "compiled",
|
|
896
2510
|
ref: this.captureRoot
|
|
897
2511
|
});
|
|
@@ -913,6 +2527,7 @@ function createKeyedRangesBlockComponent(owner) {
|
|
|
913
2527
|
this.currentProps = this.props;
|
|
914
2528
|
this.rangeInstances = [];
|
|
915
2529
|
this.staticSegments = [];
|
|
2530
|
+
this.staticValues = [];
|
|
916
2531
|
this.captureRoot = (root) => {
|
|
917
2532
|
this.root = root;
|
|
918
2533
|
this.currentProps.rootRef?.(root);
|
|
@@ -922,8 +2537,7 @@ function createKeyedRangesBlockComponent(owner) {
|
|
|
922
2537
|
};
|
|
923
2538
|
}
|
|
924
2539
|
readRange(range) {
|
|
925
|
-
const
|
|
926
|
-
const items = source ? Array.from(source) : [];
|
|
2540
|
+
const items = materializeIterable(range.items());
|
|
927
2541
|
const keys = items.map((item, index) => keyedRowIdentity(range.rowKey(item, index)));
|
|
928
2542
|
if (new Set(keys).size !== keys.length) return null;
|
|
929
2543
|
return { items, keys };
|
|
@@ -977,6 +2591,11 @@ function createKeyedRangesBlockComponent(owner) {
|
|
|
977
2591
|
staticSegments.push(elements.slice(cursor));
|
|
978
2592
|
this.staticSegments = staticSegments;
|
|
979
2593
|
this.rangeInstances = instancesByRange;
|
|
2594
|
+
if (!applyStaticRangeBindings(props.bindings, this.staticSegments, this.staticValues)) {
|
|
2595
|
+
this.rangeInstances = [];
|
|
2596
|
+
this.staticSegments = [];
|
|
2597
|
+
return false;
|
|
2598
|
+
}
|
|
980
2599
|
return true;
|
|
981
2600
|
}
|
|
982
2601
|
anchorAfter(rangeIndex) {
|
|
@@ -1053,6 +2672,14 @@ function createKeyedRangesBlockComponent(owner) {
|
|
|
1053
2672
|
this.activateFallback(afterCommit);
|
|
1054
2673
|
return;
|
|
1055
2674
|
}
|
|
2675
|
+
if (!applyStaticRangeBindings(
|
|
2676
|
+
this.currentProps.bindings,
|
|
2677
|
+
this.staticSegments,
|
|
2678
|
+
this.staticValues
|
|
2679
|
+
)) {
|
|
2680
|
+
this.activateFallback(afterCommit);
|
|
2681
|
+
return;
|
|
2682
|
+
}
|
|
1056
2683
|
const activeElement = this.root.ownerDocument.activeElement;
|
|
1057
2684
|
const restoreFocus = Boolean(activeElement && this.root.contains(activeElement));
|
|
1058
2685
|
for (let rangeIndex = rowsByRange.length - 1; rangeIndex >= 0; rangeIndex -= 1) {
|
|
@@ -1096,6 +2723,7 @@ function createKeyedRangesBlockComponent(owner) {
|
|
|
1096
2723
|
this.root = null;
|
|
1097
2724
|
this.rangeInstances = [];
|
|
1098
2725
|
this.staticSegments = [];
|
|
2726
|
+
this.staticValues.length = 0;
|
|
1099
2727
|
}
|
|
1100
2728
|
render() {
|
|
1101
2729
|
const container = this.currentProps.render();
|
|
@@ -1113,6 +2741,128 @@ function createKeyedRangesBlockComponent(owner) {
|
|
|
1113
2741
|
FarmKeyedRangesBlock.displayName = "FarmCompiledKeyedRanges";
|
|
1114
2742
|
return FarmKeyedRangesBlock;
|
|
1115
2743
|
}
|
|
2744
|
+
function createMixedRangesBlockComponent(owner) {
|
|
2745
|
+
class FarmMixedRangesBlock extends React.Component {
|
|
2746
|
+
constructor() {
|
|
2747
|
+
super(...arguments);
|
|
2748
|
+
this.state = { fallback: false };
|
|
2749
|
+
this.root = null;
|
|
2750
|
+
this.mounted = false;
|
|
2751
|
+
this.fallbackRequested = false;
|
|
2752
|
+
this.fallbackVersion = 0;
|
|
2753
|
+
this.propFallbackQueued = false;
|
|
2754
|
+
this.currentProps = this.props;
|
|
2755
|
+
this.controller = null;
|
|
2756
|
+
this.fallbackUnsubscribers = [];
|
|
2757
|
+
this.captureRoot = (root) => {
|
|
2758
|
+
this.root = root;
|
|
2759
|
+
this.currentProps.rootRef?.(root);
|
|
2760
|
+
};
|
|
2761
|
+
this.activateFallback = (afterCommit) => {
|
|
2762
|
+
if (!this.mounted || this.state.fallback || this.fallbackRequested) {
|
|
2763
|
+
afterCommit?.();
|
|
2764
|
+
return;
|
|
2765
|
+
}
|
|
2766
|
+
this.fallbackRequested = true;
|
|
2767
|
+
this.controller?.cleanup();
|
|
2768
|
+
this.controller = null;
|
|
2769
|
+
this.fallbackVersion += 1;
|
|
2770
|
+
this.setState({ fallback: true }, () => {
|
|
2771
|
+
this.subscribeFallbackBlocks();
|
|
2772
|
+
afterCommit?.();
|
|
2773
|
+
});
|
|
2774
|
+
};
|
|
2775
|
+
}
|
|
2776
|
+
clearFallbackSubscriptions() {
|
|
2777
|
+
for (const unsubscribe of this.fallbackUnsubscribers) unsubscribe();
|
|
2778
|
+
this.fallbackUnsubscribers = [];
|
|
2779
|
+
}
|
|
2780
|
+
subscribeFallbackBlocks() {
|
|
2781
|
+
this.clearFallbackSubscriptions();
|
|
2782
|
+
const descriptor = this.currentProps.create();
|
|
2783
|
+
const ids = /* @__PURE__ */ new Set();
|
|
2784
|
+
collectCompilerHostBlockIds(descriptor, ids);
|
|
2785
|
+
for (const id of ids) {
|
|
2786
|
+
this.fallbackUnsubscribers.push(
|
|
2787
|
+
owner.subscribe(id, (afterCommit) => {
|
|
2788
|
+
if (!this.mounted || !this.state.fallback) {
|
|
2789
|
+
afterCommit?.();
|
|
2790
|
+
return;
|
|
2791
|
+
}
|
|
2792
|
+
this.fallbackVersion += 1;
|
|
2793
|
+
this.forceUpdate(afterCommit);
|
|
2794
|
+
})
|
|
2795
|
+
);
|
|
2796
|
+
}
|
|
2797
|
+
}
|
|
2798
|
+
adopt() {
|
|
2799
|
+
if (!this.root) return false;
|
|
2800
|
+
const descriptor = this.currentProps.create();
|
|
2801
|
+
const block = descriptor.block;
|
|
2802
|
+
if (block?.kind !== "mixed-ranges" || block.id !== this.currentProps.id) return false;
|
|
2803
|
+
const controller = new CompilerNestedMixedRanges(
|
|
2804
|
+
owner,
|
|
2805
|
+
this.root,
|
|
2806
|
+
descriptor,
|
|
2807
|
+
block,
|
|
2808
|
+
this.activateFallback
|
|
2809
|
+
);
|
|
2810
|
+
try {
|
|
2811
|
+
if (!controller.adopt()) {
|
|
2812
|
+
controller.cleanup();
|
|
2813
|
+
return false;
|
|
2814
|
+
}
|
|
2815
|
+
} catch (error) {
|
|
2816
|
+
controller.cleanup();
|
|
2817
|
+
throw error;
|
|
2818
|
+
}
|
|
2819
|
+
this.controller = controller;
|
|
2820
|
+
return true;
|
|
2821
|
+
}
|
|
2822
|
+
schedulePropFallback() {
|
|
2823
|
+
if (this.propFallbackQueued) return;
|
|
2824
|
+
this.propFallbackQueued = true;
|
|
2825
|
+
queueMicrotask(() => {
|
|
2826
|
+
this.propFallbackQueued = false;
|
|
2827
|
+
if (this.mounted && !this.state.fallback) this.activateFallback();
|
|
2828
|
+
});
|
|
2829
|
+
}
|
|
2830
|
+
shouldComponentUpdate(nextProps, nextState) {
|
|
2831
|
+
this.currentProps = nextProps;
|
|
2832
|
+
if (nextState.fallback || this.state.fallback) return true;
|
|
2833
|
+
this.schedulePropFallback();
|
|
2834
|
+
return false;
|
|
2835
|
+
}
|
|
2836
|
+
componentDidMount() {
|
|
2837
|
+
this.mounted = true;
|
|
2838
|
+
if (!this.adopt()) this.activateFallback();
|
|
2839
|
+
}
|
|
2840
|
+
componentDidUpdate() {
|
|
2841
|
+
if (this.state.fallback) this.subscribeFallbackBlocks();
|
|
2842
|
+
}
|
|
2843
|
+
componentWillUnmount() {
|
|
2844
|
+
this.mounted = false;
|
|
2845
|
+
this.controller?.cleanup();
|
|
2846
|
+
this.controller = null;
|
|
2847
|
+
this.clearFallbackSubscriptions();
|
|
2848
|
+
this.root = null;
|
|
2849
|
+
}
|
|
2850
|
+
render() {
|
|
2851
|
+
const container = this.currentProps.render();
|
|
2852
|
+
if (!React.isValidElement(container) || typeof container.type !== "string") {
|
|
2853
|
+
throw new TypeError(
|
|
2854
|
+
`Compiled mixed ranges ${this.currentProps.id} must own one host container.`
|
|
2855
|
+
);
|
|
2856
|
+
}
|
|
2857
|
+
return React.cloneElement(container, {
|
|
2858
|
+
key: this.state.fallback ? `react-${this.fallbackVersion}` : "compiled",
|
|
2859
|
+
ref: this.captureRoot
|
|
2860
|
+
});
|
|
2861
|
+
}
|
|
2862
|
+
}
|
|
2863
|
+
FarmMixedRangesBlock.displayName = "FarmCompiledMixedRanges";
|
|
2864
|
+
return FarmMixedRangesBlock;
|
|
2865
|
+
}
|
|
1116
2866
|
function createComponentBlockComponent(owner) {
|
|
1117
2867
|
class FarmComponentBlock extends React.Component {
|
|
1118
2868
|
constructor() {
|
|
@@ -1165,6 +2915,17 @@ function createCompiledComponent(definition) {
|
|
|
1165
2915
|
this.hasBindingError = false;
|
|
1166
2916
|
this.inputSelection = null;
|
|
1167
2917
|
this.dirtyState = /* @__PURE__ */ new Set();
|
|
2918
|
+
this.indexedDefinition = null;
|
|
2919
|
+
this.staticBindingsByDependency = [];
|
|
2920
|
+
this.blockBindingsByDependency = [];
|
|
2921
|
+
this.blockBindings = /* @__PURE__ */ new Map();
|
|
2922
|
+
this.trackedBindingsByDependency = [];
|
|
2923
|
+
this.trackedDependenciesByBinding = /* @__PURE__ */ new Map();
|
|
2924
|
+
this.bindingValues = /* @__PURE__ */ new Map();
|
|
2925
|
+
this.activeBinding = null;
|
|
2926
|
+
this.activeDependencies = null;
|
|
2927
|
+
this.renderedDefinition = null;
|
|
2928
|
+
this.renderedElement = null;
|
|
1168
2929
|
this.blockRefreshListeners = /* @__PURE__ */ new Map();
|
|
1169
2930
|
this.blockRoots = /* @__PURE__ */ new Map();
|
|
1170
2931
|
this.blockRootElements = /* @__PURE__ */ new Set();
|
|
@@ -1176,20 +2937,35 @@ function createCompiledComponent(definition) {
|
|
|
1176
2937
|
this.refreshDefinition = () => {
|
|
1177
2938
|
if (this.mounted) this.forceUpdate();
|
|
1178
2939
|
};
|
|
1179
|
-
|
|
2940
|
+
const initialState = definitionReference.current.initialize(props);
|
|
2941
|
+
const initialProps = definitionReference.current.readProps?.(props) || [];
|
|
2942
|
+
this.propCellOffset = initialState.length;
|
|
2943
|
+
this.cells = [...initialState, ...initialProps].map((initialValue, index) => {
|
|
1180
2944
|
let value = initialValue;
|
|
1181
2945
|
const pending = [];
|
|
1182
2946
|
return {
|
|
1183
|
-
get: () =>
|
|
2947
|
+
get: () => {
|
|
2948
|
+
if (this.activeBinding && this.activeDependencies) {
|
|
2949
|
+
this.activeDependencies.add(index);
|
|
2950
|
+
}
|
|
2951
|
+
return value;
|
|
2952
|
+
},
|
|
1184
2953
|
set: (next) => {
|
|
1185
|
-
pending.push(next);
|
|
2954
|
+
pending.push({ kind: "state", update: next });
|
|
1186
2955
|
this.scheduleBindingFlush(index);
|
|
1187
2956
|
},
|
|
2957
|
+
replace: (next) => {
|
|
2958
|
+
pending.push({ kind: "value", value: next });
|
|
2959
|
+
},
|
|
1188
2960
|
flush: () => {
|
|
1189
2961
|
if (pending.length === 0) return false;
|
|
1190
2962
|
const previous = value;
|
|
1191
2963
|
for (const next of pending.splice(0)) {
|
|
1192
|
-
|
|
2964
|
+
if (next.kind === "value") {
|
|
2965
|
+
value = next.value;
|
|
2966
|
+
} else {
|
|
2967
|
+
value = typeof next.update === "function" ? next.update(value) : next.update;
|
|
2968
|
+
}
|
|
1193
2969
|
}
|
|
1194
2970
|
return !Object.is(previous, value);
|
|
1195
2971
|
}
|
|
@@ -1203,6 +2979,9 @@ function createCompiledComponent(definition) {
|
|
|
1203
2979
|
HostConditional: createHostConditionalBlockComponent({
|
|
1204
2980
|
subscribe: (id, refresh) => this.subscribeToBlock(id, refresh)
|
|
1205
2981
|
}),
|
|
2982
|
+
ConditionalRanges: createConditionalRangesBlockComponent({
|
|
2983
|
+
subscribe: (id, refresh) => this.subscribeToBlock(id, refresh)
|
|
2984
|
+
}),
|
|
1206
2985
|
KeyedList: createKeyedListBlockComponent({
|
|
1207
2986
|
subscribe: (id, refresh) => this.subscribeToBlock(id, refresh)
|
|
1208
2987
|
}),
|
|
@@ -1212,12 +2991,113 @@ function createCompiledComponent(definition) {
|
|
|
1212
2991
|
KeyedRanges: createKeyedRangesBlockComponent({
|
|
1213
2992
|
subscribe: (id, refresh) => this.subscribeToBlock(id, refresh)
|
|
1214
2993
|
}),
|
|
2994
|
+
MixedRanges: createMixedRangesBlockComponent({
|
|
2995
|
+
subscribe: (id, refresh) => this.subscribeToBlock(id, refresh)
|
|
2996
|
+
}),
|
|
1215
2997
|
Component: createComponentBlockComponent({
|
|
1216
2998
|
subscribe: (id, refresh) => this.subscribeToBlock(id, refresh)
|
|
1217
2999
|
}),
|
|
1218
3000
|
target: (id) => this.bindingTarget(id)
|
|
1219
3001
|
};
|
|
1220
3002
|
}
|
|
3003
|
+
usesHybridReactivity() {
|
|
3004
|
+
return definitionReference.current.reactivity === "hybrid";
|
|
3005
|
+
}
|
|
3006
|
+
canReuseRenderedElement(currentDefinition, propValues) {
|
|
3007
|
+
return Boolean(
|
|
3008
|
+
this.mounted && propValues && propValues.every(isCompilerPrimitive) && this.renderedDefinition === currentDefinition && this.renderedElement
|
|
3009
|
+
);
|
|
3010
|
+
}
|
|
3011
|
+
renderCellsForProps(propValues) {
|
|
3012
|
+
if (!propValues) return { cells: this.cells, commit: () => void 0 };
|
|
3013
|
+
let committed = false;
|
|
3014
|
+
const cells = this.cells.slice(0, this.propCellOffset);
|
|
3015
|
+
for (let propIndex = 0; propIndex < propValues.length; propIndex += 1) {
|
|
3016
|
+
const cell = this.cells[this.propCellOffset + propIndex];
|
|
3017
|
+
if (!cell) continue;
|
|
3018
|
+
cells.push({
|
|
3019
|
+
get: () => committed ? cell.get() : propValues[propIndex],
|
|
3020
|
+
set: (next) => cell.set(next)
|
|
3021
|
+
});
|
|
3022
|
+
}
|
|
3023
|
+
return {
|
|
3024
|
+
cells,
|
|
3025
|
+
commit: () => {
|
|
3026
|
+
committed = true;
|
|
3027
|
+
}
|
|
3028
|
+
};
|
|
3029
|
+
}
|
|
3030
|
+
tracksBinding(binding) {
|
|
3031
|
+
return this.usesHybridReactivity() && binding.tracking === "dynamic";
|
|
3032
|
+
}
|
|
3033
|
+
ensureBindingIndex() {
|
|
3034
|
+
const currentDefinition = definitionReference.current;
|
|
3035
|
+
if (this.indexedDefinition === currentDefinition) return;
|
|
3036
|
+
this.indexedDefinition = currentDefinition;
|
|
3037
|
+
this.staticBindingsByDependency = Array.from({ length: this.cells.length }, () => []);
|
|
3038
|
+
this.blockBindingsByDependency = Array.from({ length: this.cells.length }, () => []);
|
|
3039
|
+
this.trackedBindingsByDependency = Array.from(
|
|
3040
|
+
{ length: this.cells.length },
|
|
3041
|
+
() => /* @__PURE__ */ new Set()
|
|
3042
|
+
);
|
|
3043
|
+
this.blockBindings.clear();
|
|
3044
|
+
this.trackedDependenciesByBinding.clear();
|
|
3045
|
+
this.bindingValues.clear();
|
|
3046
|
+
for (const binding of currentDefinition.bindings) {
|
|
3047
|
+
if (binding.kind === "block") this.blockBindings.set(binding.id, binding);
|
|
3048
|
+
for (const dependency of binding.dependencies) {
|
|
3049
|
+
if (dependency < 0 || dependency >= this.cells.length) continue;
|
|
3050
|
+
if (binding.kind === "block") {
|
|
3051
|
+
this.blockBindingsByDependency[dependency].push(binding);
|
|
3052
|
+
} else if (!this.tracksBinding(binding)) {
|
|
3053
|
+
this.staticBindingsByDependency[dependency].push(binding);
|
|
3054
|
+
}
|
|
3055
|
+
}
|
|
3056
|
+
}
|
|
3057
|
+
}
|
|
3058
|
+
updateTrackedDependencies(binding, nextDependencies) {
|
|
3059
|
+
const previousDependencies = this.trackedDependenciesByBinding.get(binding);
|
|
3060
|
+
if (previousDependencies) {
|
|
3061
|
+
for (const dependency of previousDependencies) {
|
|
3062
|
+
if (!nextDependencies.has(dependency)) {
|
|
3063
|
+
this.trackedBindingsByDependency[dependency]?.delete(binding);
|
|
3064
|
+
}
|
|
3065
|
+
}
|
|
3066
|
+
}
|
|
3067
|
+
for (const dependency of nextDependencies) {
|
|
3068
|
+
if (!previousDependencies?.has(dependency)) {
|
|
3069
|
+
this.trackedBindingsByDependency[dependency]?.add(binding);
|
|
3070
|
+
}
|
|
3071
|
+
}
|
|
3072
|
+
this.trackedDependenciesByBinding.set(binding, nextDependencies);
|
|
3073
|
+
}
|
|
3074
|
+
readBinding(binding) {
|
|
3075
|
+
if (!this.tracksBinding(binding)) return binding.read(this.props, this.cells);
|
|
3076
|
+
const previousBinding = this.activeBinding;
|
|
3077
|
+
const previousDependencies = this.activeDependencies;
|
|
3078
|
+
const nextDependencies = /* @__PURE__ */ new Set();
|
|
3079
|
+
this.activeBinding = binding;
|
|
3080
|
+
this.activeDependencies = nextDependencies;
|
|
3081
|
+
try {
|
|
3082
|
+
return binding.read(this.props, this.cells);
|
|
3083
|
+
} finally {
|
|
3084
|
+
this.activeBinding = previousBinding;
|
|
3085
|
+
this.activeDependencies = previousDependencies;
|
|
3086
|
+
this.updateTrackedDependencies(binding, nextDependencies);
|
|
3087
|
+
}
|
|
3088
|
+
}
|
|
3089
|
+
bindingValue(binding, value) {
|
|
3090
|
+
return binding.kind === "text" ? renderTextValue(value) : value;
|
|
3091
|
+
}
|
|
3092
|
+
primeHybridBindings() {
|
|
3093
|
+
if (!this.usesHybridReactivity()) return;
|
|
3094
|
+
for (const binding of definitionReference.current.bindings) {
|
|
3095
|
+
if (binding.kind === "block") continue;
|
|
3096
|
+
if (!this.tracksBinding(binding)) continue;
|
|
3097
|
+
const value = this.readBinding(binding);
|
|
3098
|
+
this.bindingValues.set(binding, this.bindingValue(binding, value));
|
|
3099
|
+
}
|
|
3100
|
+
}
|
|
1221
3101
|
bindingTarget(id) {
|
|
1222
3102
|
const existing = this.bindingTargetRefs.get(id);
|
|
1223
3103
|
if (existing) return existing;
|
|
@@ -1274,83 +3154,118 @@ function createCompiledComponent(definition) {
|
|
|
1274
3154
|
this.flushQueued = true;
|
|
1275
3155
|
queueMicrotask(() => {
|
|
1276
3156
|
this.flushQueued = false;
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
3157
|
+
this.flushBindingUpdates();
|
|
3158
|
+
});
|
|
3159
|
+
}
|
|
3160
|
+
flushBindingUpdates() {
|
|
3161
|
+
const inputSelection = this.inputSelection;
|
|
3162
|
+
this.inputSelection = null;
|
|
3163
|
+
if (!this.mounted) return;
|
|
3164
|
+
const dirty = /* @__PURE__ */ new Set();
|
|
3165
|
+
for (const index of this.dirtyState) {
|
|
3166
|
+
if (this.cells[index]?.flush()) dirty.add(index);
|
|
3167
|
+
}
|
|
3168
|
+
this.dirtyState.clear();
|
|
3169
|
+
if (dirty.size === 0) return;
|
|
3170
|
+
try {
|
|
3171
|
+
this.ensureBindingIndex();
|
|
3172
|
+
const affectedBlockIds = /* @__PURE__ */ new Set();
|
|
3173
|
+
const affectedBindings = /* @__PURE__ */ new Set();
|
|
3174
|
+
for (const dependency of dirty) {
|
|
3175
|
+
for (const binding of this.blockBindingsByDependency[dependency] || []) {
|
|
3176
|
+
affectedBlockIds.add(binding.id);
|
|
1296
3177
|
}
|
|
1297
|
-
const
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
parent = blockBindings.get(parent)?.parent;
|
|
1304
|
-
}
|
|
1305
|
-
return false;
|
|
1306
|
-
};
|
|
1307
|
-
const blockRefreshes = [...affectedBlockIds].map((id) => {
|
|
1308
|
-
const binding = blockBindings.get(id);
|
|
1309
|
-
const refresh = this.blockRefreshListeners.get(id);
|
|
1310
|
-
return binding && refresh && !hasAffectedMountedAncestor(binding) ? refresh : void 0;
|
|
1311
|
-
}).filter(
|
|
1312
|
-
(refresh) => refresh !== void 0
|
|
1313
|
-
);
|
|
1314
|
-
for (const binding of bindings) {
|
|
1315
|
-
if (binding.kind !== "block" && binding.dependencies.some((dependency) => dirty.has(dependency))) {
|
|
1316
|
-
this.applyBinding(binding);
|
|
3178
|
+
for (const binding of this.staticBindingsByDependency[dependency] || []) {
|
|
3179
|
+
affectedBindings.add(binding);
|
|
3180
|
+
}
|
|
3181
|
+
if (this.usesHybridReactivity()) {
|
|
3182
|
+
for (const binding of this.trackedBindingsByDependency[dependency] || []) {
|
|
3183
|
+
affectedBindings.add(binding);
|
|
1317
3184
|
}
|
|
1318
3185
|
}
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
3186
|
+
}
|
|
3187
|
+
const hasAffectedMountedAncestor = (binding) => {
|
|
3188
|
+
let parent = binding.parent;
|
|
3189
|
+
while (parent !== void 0) {
|
|
3190
|
+
if (affectedBlockIds.has(parent) && this.blockRefreshListeners.has(parent)) {
|
|
3191
|
+
return true;
|
|
3192
|
+
}
|
|
3193
|
+
parent = this.blockBindings.get(parent)?.parent;
|
|
1325
3194
|
}
|
|
1326
|
-
|
|
1327
|
-
}
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
this.
|
|
3195
|
+
return false;
|
|
3196
|
+
};
|
|
3197
|
+
const blockRefreshes = [...affectedBlockIds].map((id) => {
|
|
3198
|
+
const binding = this.blockBindings.get(id);
|
|
3199
|
+
const refresh = this.blockRefreshListeners.get(id);
|
|
3200
|
+
return binding && refresh && !hasAffectedMountedAncestor(binding) ? refresh : void 0;
|
|
3201
|
+
}).filter((refresh) => refresh !== void 0);
|
|
3202
|
+
for (const binding of affectedBindings) {
|
|
3203
|
+
if (binding.kind !== "block") this.applyBinding(binding);
|
|
1331
3204
|
}
|
|
1332
|
-
|
|
3205
|
+
let pendingBlockCommits = blockRefreshes.length;
|
|
3206
|
+
for (const refresh of blockRefreshes) {
|
|
3207
|
+
refresh(() => {
|
|
3208
|
+
pendingBlockCommits -= 1;
|
|
3209
|
+
if (pendingBlockCommits === 0) this.restoreInputSelection(inputSelection);
|
|
3210
|
+
}, dirty);
|
|
3211
|
+
}
|
|
3212
|
+
if (blockRefreshes.length === 0) this.restoreInputSelection(inputSelection);
|
|
3213
|
+
} catch (error) {
|
|
3214
|
+
this.bindingError = error;
|
|
3215
|
+
this.hasBindingError = true;
|
|
3216
|
+
this.forceUpdate();
|
|
3217
|
+
}
|
|
1333
3218
|
}
|
|
1334
|
-
applyBinding(binding) {
|
|
3219
|
+
applyBinding(binding, force = false) {
|
|
1335
3220
|
if (!this.root || binding.kind === "block") return;
|
|
1336
3221
|
const target = binding.target === void 0 ? findBindingTarget(this.root, binding.path, this.blockRootElements) : binding.path.length === 0 ? this.root : this.bindingTargets.get(binding.target) || null;
|
|
1337
3222
|
if (!target) return;
|
|
1338
|
-
const value =
|
|
3223
|
+
const value = this.readBinding(binding);
|
|
3224
|
+
const comparableValue = this.bindingValue(binding, value);
|
|
3225
|
+
if (!force && this.bindingValues.has(binding)) {
|
|
3226
|
+
if (Object.is(this.bindingValues.get(binding), comparableValue)) return;
|
|
3227
|
+
}
|
|
1339
3228
|
if (binding.kind === "text") {
|
|
1340
|
-
target.textContent =
|
|
3229
|
+
target.textContent = comparableValue;
|
|
1341
3230
|
} else if (binding.kind === "style") {
|
|
1342
3231
|
updateStyle(target, binding.name, value);
|
|
1343
3232
|
} else {
|
|
1344
3233
|
updateAttribute(target, binding.name, value);
|
|
1345
3234
|
}
|
|
3235
|
+
this.bindingValues.set(binding, comparableValue);
|
|
1346
3236
|
}
|
|
1347
3237
|
componentDidMount() {
|
|
1348
3238
|
this.mounted = true;
|
|
1349
3239
|
refreshListeners.add(this.refreshDefinition);
|
|
3240
|
+
this.ensureBindingIndex();
|
|
3241
|
+
this.primeHybridBindings();
|
|
1350
3242
|
}
|
|
1351
|
-
|
|
3243
|
+
getSnapshotBeforeUpdate() {
|
|
3244
|
+
const currentDefinition = definitionReference.current;
|
|
3245
|
+
const propValues = currentDefinition.readProps?.(this.props) || null;
|
|
3246
|
+
return this.canReuseRenderedElement(currentDefinition, propValues);
|
|
3247
|
+
}
|
|
3248
|
+
componentDidUpdate(_previousProps, _previousState, reusedRenderedElement = false) {
|
|
3249
|
+
const propValues = definitionReference.current.readProps?.(this.props) || null;
|
|
3250
|
+
if (propValues) {
|
|
3251
|
+
if (reusedRenderedElement) this.captureInputSelection();
|
|
3252
|
+
for (let propIndex = 0; propIndex < propValues.length; propIndex += 1) {
|
|
3253
|
+
const cellIndex = this.propCellOffset + propIndex;
|
|
3254
|
+
const cell = this.cells[cellIndex];
|
|
3255
|
+
if (!cell) continue;
|
|
3256
|
+
cell.replace(propValues[propIndex]);
|
|
3257
|
+
if (reusedRenderedElement) {
|
|
3258
|
+
this.dirtyState.add(cellIndex);
|
|
3259
|
+
} else {
|
|
3260
|
+
cell.flush();
|
|
3261
|
+
}
|
|
3262
|
+
}
|
|
3263
|
+
this.flushBindingUpdates();
|
|
3264
|
+
return;
|
|
3265
|
+
}
|
|
3266
|
+
this.ensureBindingIndex();
|
|
1352
3267
|
for (const binding of definitionReference.current.bindings) {
|
|
1353
|
-
if (binding.kind !== "block") this.applyBinding(binding);
|
|
3268
|
+
if (binding.kind !== "block") this.applyBinding(binding, true);
|
|
1354
3269
|
}
|
|
1355
3270
|
}
|
|
1356
3271
|
componentWillUnmount() {
|
|
@@ -1363,30 +3278,68 @@ function createCompiledComponent(definition) {
|
|
|
1363
3278
|
this.blockRootElements.clear();
|
|
1364
3279
|
this.bindingTargets.clear();
|
|
1365
3280
|
this.bindingTargetRefs.clear();
|
|
3281
|
+
this.indexedDefinition = null;
|
|
3282
|
+
this.staticBindingsByDependency = [];
|
|
3283
|
+
this.blockBindingsByDependency = [];
|
|
3284
|
+
this.blockBindings.clear();
|
|
3285
|
+
this.trackedBindingsByDependency = [];
|
|
3286
|
+
this.trackedDependenciesByBinding.clear();
|
|
3287
|
+
this.bindingValues.clear();
|
|
3288
|
+
this.activeBinding = null;
|
|
3289
|
+
this.activeDependencies = null;
|
|
1366
3290
|
refreshListeners.delete(this.refreshDefinition);
|
|
1367
3291
|
}
|
|
1368
3292
|
render() {
|
|
1369
3293
|
if (this.hasBindingError) throw this.bindingError;
|
|
1370
3294
|
const currentDefinition = definitionReference.current;
|
|
1371
|
-
const
|
|
3295
|
+
const propValues = currentDefinition.readProps?.(this.props) || null;
|
|
3296
|
+
if (this.canReuseRenderedElement(currentDefinition, propValues)) {
|
|
3297
|
+
return this.renderedElement;
|
|
3298
|
+
}
|
|
3299
|
+
const renderCells = this.renderCellsForProps(propValues);
|
|
3300
|
+
const element = currentDefinition.render(this.props, renderCells.cells, this.blockRuntime);
|
|
1372
3301
|
if (!React.isValidElement(element)) {
|
|
1373
3302
|
throw new TypeError(
|
|
1374
3303
|
`Compiled component ${currentDefinition.displayName} must return one host element.`
|
|
1375
3304
|
);
|
|
1376
3305
|
}
|
|
3306
|
+
let renderedElement;
|
|
3307
|
+
const captureCommittedRoot = (root) => {
|
|
3308
|
+
this.captureRoot(root);
|
|
3309
|
+
if (!root) return;
|
|
3310
|
+
renderCells.commit();
|
|
3311
|
+
this.renderedDefinition = currentDefinition;
|
|
3312
|
+
this.renderedElement = renderedElement;
|
|
3313
|
+
};
|
|
1377
3314
|
if (element.type === this.blockRuntime.KeyedRanges) {
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
3315
|
+
renderedElement = React.cloneElement(
|
|
3316
|
+
element,
|
|
3317
|
+
{
|
|
3318
|
+
rootRef: captureCommittedRoot
|
|
3319
|
+
}
|
|
3320
|
+
);
|
|
3321
|
+
} else if (element.type === this.blockRuntime.ConditionalRanges) {
|
|
3322
|
+
renderedElement = React.cloneElement(
|
|
3323
|
+
element,
|
|
3324
|
+
{ rootRef: captureCommittedRoot }
|
|
3325
|
+
);
|
|
3326
|
+
} else if (element.type === this.blockRuntime.MixedRanges) {
|
|
3327
|
+
renderedElement = React.cloneElement(
|
|
3328
|
+
element,
|
|
3329
|
+
{
|
|
3330
|
+
rootRef: captureCommittedRoot
|
|
3331
|
+
}
|
|
3332
|
+
);
|
|
3333
|
+
} else if (typeof element.type !== "string") {
|
|
1383
3334
|
throw new TypeError(
|
|
1384
3335
|
`Compiled component ${currentDefinition.displayName} must return one host element.`
|
|
1385
3336
|
);
|
|
3337
|
+
} else {
|
|
3338
|
+
renderedElement = React.cloneElement(element, {
|
|
3339
|
+
ref: captureCommittedRoot
|
|
3340
|
+
});
|
|
1386
3341
|
}
|
|
1387
|
-
return
|
|
1388
|
-
ref: this.captureRoot
|
|
1389
|
-
});
|
|
3342
|
+
return renderedElement;
|
|
1390
3343
|
}
|
|
1391
3344
|
}
|
|
1392
3345
|
FarmCompiledComponent.displayName = `FarmCompiled(${definition.displayName})`;
|