@farm.js/react 0.1.0-beta.3 → 0.1.0-beta.5
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 +133 -37
- package/dist/compiler-runtime.cjs +2052 -188
- package/dist/compiler-runtime.cjs.map +1 -1
- package/dist/compiler-runtime.d.mts +106 -4
- package/dist/compiler-runtime.d.ts +106 -4
- package/dist/compiler-runtime.mjs +2041 -189
- 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 +1224 -87
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.mjs +1224 -87
- package/dist/vite.mjs.map +1 -1
- package/package.json +6 -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;
|
|
@@ -515,8 +1592,14 @@ function createConditionalRangesBlockComponent(owner) {
|
|
|
515
1592
|
this.fallbackVersion = 0;
|
|
516
1593
|
this.propFallbackQueued = false;
|
|
517
1594
|
this.currentProps = this.props;
|
|
1595
|
+
this.fallbackUnsubscribers = [];
|
|
518
1596
|
this.rangeInstances = [];
|
|
519
1597
|
this.staticSegments = [];
|
|
1598
|
+
this.staticValues = [];
|
|
1599
|
+
this.requestNestedFallback = () => {
|
|
1600
|
+
for (const instance of this.rangeInstances) instance?.host.scope?.cleanup();
|
|
1601
|
+
this.activateFallback();
|
|
1602
|
+
};
|
|
520
1603
|
this.captureRoot = (root) => {
|
|
521
1604
|
this.root = root;
|
|
522
1605
|
this.currentProps.rootRef?.(root);
|
|
@@ -525,6 +1608,24 @@ function createConditionalRangesBlockComponent(owner) {
|
|
|
525
1608
|
this.reconcile(afterCommit);
|
|
526
1609
|
};
|
|
527
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
|
+
}
|
|
528
1629
|
readSelections(props) {
|
|
529
1630
|
const selections = [];
|
|
530
1631
|
for (const range of props.ranges) {
|
|
@@ -541,12 +1642,21 @@ function createConditionalRangesBlockComponent(owner) {
|
|
|
541
1642
|
const elements = [...this.root.children];
|
|
542
1643
|
const staticSegments = [];
|
|
543
1644
|
const instances = [];
|
|
1645
|
+
const cleanupInstances = () => {
|
|
1646
|
+
for (const instance of instances) instance?.host.scope?.cleanup();
|
|
1647
|
+
};
|
|
544
1648
|
let cursor = 0;
|
|
545
1649
|
for (let rangeIndex = 0; rangeIndex < props.ranges.length; rangeIndex += 1) {
|
|
546
1650
|
const range = props.ranges[rangeIndex];
|
|
547
|
-
if (!Number.isSafeInteger(range.before) || range.before < 0)
|
|
1651
|
+
if (!Number.isSafeInteger(range.before) || range.before < 0) {
|
|
1652
|
+
cleanupInstances();
|
|
1653
|
+
return false;
|
|
1654
|
+
}
|
|
548
1655
|
const staticEnd = cursor + range.before;
|
|
549
|
-
if (staticEnd > elements.length)
|
|
1656
|
+
if (staticEnd > elements.length) {
|
|
1657
|
+
cleanupInstances();
|
|
1658
|
+
return false;
|
|
1659
|
+
}
|
|
550
1660
|
staticSegments.push(elements.slice(cursor, staticEnd));
|
|
551
1661
|
cursor = staticEnd;
|
|
552
1662
|
const selection = selections[rangeIndex];
|
|
@@ -555,22 +1665,45 @@ function createConditionalRangesBlockComponent(owner) {
|
|
|
555
1665
|
continue;
|
|
556
1666
|
}
|
|
557
1667
|
const element = elements[cursor];
|
|
558
|
-
if (!element)
|
|
1668
|
+
if (!element) {
|
|
1669
|
+
cleanupInstances();
|
|
1670
|
+
return false;
|
|
1671
|
+
}
|
|
559
1672
|
const descriptor = selection.branch.create();
|
|
560
|
-
if (!matchesCompilerHostElement(element, descriptor))
|
|
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
|
+
}
|
|
561
1688
|
instances.push({
|
|
562
1689
|
key: selection.key,
|
|
563
|
-
host
|
|
564
|
-
element,
|
|
565
|
-
values: readHostConditionalBindingValues(selection.branch)
|
|
566
|
-
}
|
|
1690
|
+
host
|
|
567
1691
|
});
|
|
568
1692
|
cursor += 1;
|
|
569
1693
|
}
|
|
570
|
-
if (cursor + props.trailing !== elements.length)
|
|
1694
|
+
if (cursor + props.trailing !== elements.length) {
|
|
1695
|
+
cleanupInstances();
|
|
1696
|
+
return false;
|
|
1697
|
+
}
|
|
571
1698
|
staticSegments.push(elements.slice(cursor));
|
|
572
1699
|
this.staticSegments = staticSegments;
|
|
573
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
|
+
}
|
|
574
1707
|
return true;
|
|
575
1708
|
}
|
|
576
1709
|
anchorAfter(rangeIndex) {
|
|
@@ -583,27 +1716,52 @@ function createConditionalRangesBlockComponent(owner) {
|
|
|
583
1716
|
return this.staticSegments[this.rangeInstances.length]?.[0] || null;
|
|
584
1717
|
}
|
|
585
1718
|
reconcileRange(rangeIndex, selection) {
|
|
586
|
-
if (!this.root) return;
|
|
1719
|
+
if (!this.root) return false;
|
|
587
1720
|
const previous = this.rangeInstances[rangeIndex];
|
|
588
1721
|
if (selection.kind === "empty") {
|
|
1722
|
+
previous?.host.scope?.cleanup();
|
|
589
1723
|
previous?.host.element.remove();
|
|
590
1724
|
this.rangeInstances[rangeIndex] = null;
|
|
591
|
-
return;
|
|
1725
|
+
return true;
|
|
592
1726
|
}
|
|
593
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;
|
|
594
1741
|
applyHostConditionalBindings(selection.branch, previous.host);
|
|
595
|
-
return;
|
|
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;
|
|
596
1756
|
}
|
|
597
|
-
|
|
1757
|
+
previous?.host.scope?.cleanup();
|
|
598
1758
|
if (previous) previous.host.element.replaceWith(element);
|
|
599
1759
|
else this.root.insertBefore(element, this.anchorAfter(rangeIndex));
|
|
600
1760
|
this.rangeInstances[rangeIndex] = {
|
|
601
1761
|
key: selection.key,
|
|
602
|
-
host
|
|
603
|
-
element,
|
|
604
|
-
values: readHostConditionalBindingValues(selection.branch)
|
|
605
|
-
}
|
|
1762
|
+
host
|
|
606
1763
|
};
|
|
1764
|
+
return true;
|
|
607
1765
|
}
|
|
608
1766
|
reconcile(afterCommit) {
|
|
609
1767
|
if (!this.mounted || !this.root) {
|
|
@@ -624,8 +1782,19 @@ function createConditionalRangesBlockComponent(owner) {
|
|
|
624
1782
|
this.activateFallback(afterCommit);
|
|
625
1783
|
return;
|
|
626
1784
|
}
|
|
1785
|
+
if (!applyStaticRangeBindings(
|
|
1786
|
+
this.currentProps.bindings,
|
|
1787
|
+
this.staticSegments,
|
|
1788
|
+
this.staticValues
|
|
1789
|
+
)) {
|
|
1790
|
+
this.activateFallback(afterCommit);
|
|
1791
|
+
return;
|
|
1792
|
+
}
|
|
627
1793
|
for (let rangeIndex = this.rangeInstances.length - 1; rangeIndex >= 0; rangeIndex -= 1) {
|
|
628
|
-
this.reconcileRange(rangeIndex, selections[rangeIndex])
|
|
1794
|
+
if (!this.reconcileRange(rangeIndex, selections[rangeIndex])) {
|
|
1795
|
+
afterCommit?.();
|
|
1796
|
+
return;
|
|
1797
|
+
}
|
|
629
1798
|
}
|
|
630
1799
|
afterCommit?.();
|
|
631
1800
|
}
|
|
@@ -635,6 +1804,8 @@ function createConditionalRangesBlockComponent(owner) {
|
|
|
635
1804
|
return;
|
|
636
1805
|
}
|
|
637
1806
|
this.fallbackRequested = true;
|
|
1807
|
+
for (const instance of this.rangeInstances) instance?.host.scope?.cleanup();
|
|
1808
|
+
this.subscribeFallbackDescendants();
|
|
638
1809
|
this.setState({ fallback: true }, afterCommit);
|
|
639
1810
|
}
|
|
640
1811
|
schedulePropFallback() {
|
|
@@ -659,9 +1830,13 @@ function createConditionalRangesBlockComponent(owner) {
|
|
|
659
1830
|
componentWillUnmount() {
|
|
660
1831
|
this.mounted = false;
|
|
661
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();
|
|
662
1836
|
this.root = null;
|
|
663
1837
|
this.rangeInstances = [];
|
|
664
1838
|
this.staticSegments = [];
|
|
1839
|
+
this.staticValues.length = 0;
|
|
665
1840
|
}
|
|
666
1841
|
render() {
|
|
667
1842
|
const container = this.currentProps.render();
|
|
@@ -702,7 +1877,7 @@ function longestIncreasingSubsequencePositions(sequence) {
|
|
|
702
1877
|
}
|
|
703
1878
|
return positions;
|
|
704
1879
|
}
|
|
705
|
-
function
|
|
1880
|
+
function createKeyedRowConditionalRuntime() {
|
|
706
1881
|
class FarmKeyedRowConditional extends React.Component {
|
|
707
1882
|
constructor() {
|
|
708
1883
|
super(...arguments);
|
|
@@ -744,6 +1919,22 @@ function createKeyedRowsBlockComponent(owner) {
|
|
|
744
1919
|
}
|
|
745
1920
|
}
|
|
746
1921
|
FarmKeyedRowConditional.displayName = "FarmCompiledKeyedRowConditional";
|
|
1922
|
+
return {
|
|
1923
|
+
Component: FarmKeyedRowConditional,
|
|
1924
|
+
readValues: readKeyedRowConditionalValues,
|
|
1925
|
+
changed: keyedRowConditionalChanged
|
|
1926
|
+
};
|
|
1927
|
+
}
|
|
1928
|
+
function createKeyedRowHostRuntime() {
|
|
1929
|
+
const owner = {
|
|
1930
|
+
subscribe: () => () => {
|
|
1931
|
+
}
|
|
1932
|
+
};
|
|
1933
|
+
return {
|
|
1934
|
+
mount: (element, descriptor, requestFallback) => mountCompilerHostTree(owner, element, descriptor, requestFallback)
|
|
1935
|
+
};
|
|
1936
|
+
}
|
|
1937
|
+
function createKeyedRowsBlockComponent(owner, options = {}) {
|
|
747
1938
|
class FarmKeyedRowsBlock extends React.Component {
|
|
748
1939
|
constructor() {
|
|
749
1940
|
super(...arguments);
|
|
@@ -759,16 +1950,23 @@ function createKeyedRowsBlockComponent(owner) {
|
|
|
759
1950
|
this.renderVersion = 0;
|
|
760
1951
|
this.eventHandlers = /* @__PURE__ */ new Map();
|
|
761
1952
|
this.conditionalListeners = /* @__PURE__ */ new Map();
|
|
1953
|
+
this.instancesByElement = /* @__PURE__ */ new WeakMap();
|
|
762
1954
|
this.conditionalOwner = {
|
|
763
1955
|
subscribe: (key, id, refresh) => this.subscribeToRowConditional(key, id, refresh)
|
|
764
1956
|
};
|
|
765
1957
|
this.captureRoot = (root) => {
|
|
766
1958
|
this.root = root;
|
|
767
1959
|
};
|
|
1960
|
+
this.requestHostScopeFallback = () => {
|
|
1961
|
+
this.activateFallback();
|
|
1962
|
+
};
|
|
768
1963
|
this.rowEvent = (item, index, eventId) => {
|
|
769
1964
|
if (this.state.fallback) {
|
|
770
1965
|
return (event) => this.currentProps.events?.[eventId]?.invoke(item, index, event);
|
|
771
1966
|
}
|
|
1967
|
+
if (this.usesDelegatedEvents()) {
|
|
1968
|
+
return void 0;
|
|
1969
|
+
}
|
|
772
1970
|
const key = keyedRowIdentity(this.currentProps.rowKey(item, index));
|
|
773
1971
|
let handlers = this.eventHandlers.get(key);
|
|
774
1972
|
if (!handlers) {
|
|
@@ -786,10 +1984,32 @@ function createKeyedRowsBlockComponent(owner) {
|
|
|
786
1984
|
handlers.set(eventId, handler);
|
|
787
1985
|
return handler;
|
|
788
1986
|
};
|
|
1987
|
+
this.dispatchDelegatedEvent = (name, event) => {
|
|
1988
|
+
const instance = this.eventRowInstance(event);
|
|
1989
|
+
const eventTarget = event.target;
|
|
1990
|
+
if (!instance || !eventTarget) return;
|
|
1991
|
+
const capture = name.endsWith("Capture");
|
|
1992
|
+
const matches = (this.currentProps.events || []).filter((descriptor) => descriptor.name === name && descriptor.path !== void 0).map((descriptor) => ({
|
|
1993
|
+
descriptor,
|
|
1994
|
+
target: findCompilerHostTarget(instance.element, descriptor.path || [])
|
|
1995
|
+
})).filter(
|
|
1996
|
+
(match) => Boolean(
|
|
1997
|
+
match.target && (match.target === eventTarget || match.target.contains(eventTarget))
|
|
1998
|
+
)
|
|
1999
|
+
).sort(
|
|
2000
|
+
(left, right) => capture ? (left.descriptor.path?.length || 0) - (right.descriptor.path?.length || 0) : (right.descriptor.path?.length || 0) - (left.descriptor.path?.length || 0)
|
|
2001
|
+
);
|
|
2002
|
+
for (const match of matches) {
|
|
2003
|
+
this.invokeDelegatedEvent(match.descriptor, instance, event, match.target);
|
|
2004
|
+
if (event.isPropagationStopped()) break;
|
|
2005
|
+
}
|
|
2006
|
+
};
|
|
789
2007
|
this.rowConditional = (item, index, conditionalId, render) => {
|
|
790
2008
|
if (this.state.fallback) return render(item, index);
|
|
791
2009
|
const key = keyedRowIdentity(this.currentProps.rowKey(item, index));
|
|
792
|
-
|
|
2010
|
+
const Conditional = options.conditionals?.Component;
|
|
2011
|
+
if (!Conditional) return render(item, index);
|
|
2012
|
+
return React.createElement(Conditional, {
|
|
793
2013
|
key: `${key}:${conditionalId}`,
|
|
794
2014
|
owner: this.conditionalOwner,
|
|
795
2015
|
rowKey: key,
|
|
@@ -800,17 +2020,65 @@ function createKeyedRowsBlockComponent(owner) {
|
|
|
800
2020
|
render
|
|
801
2021
|
});
|
|
802
2022
|
};
|
|
803
|
-
this.refresh = (afterCommit) => {
|
|
2023
|
+
this.refresh = (afterCommit, dirtyState) => {
|
|
2024
|
+
if (dirtyState && this.refreshDirtyBindings(dirtyState, afterCommit)) return;
|
|
804
2025
|
this.reconcile(afterCommit);
|
|
805
2026
|
};
|
|
806
2027
|
}
|
|
807
2028
|
readRows(props) {
|
|
808
|
-
const
|
|
809
|
-
const items = source ? Array.from(source) : [];
|
|
2029
|
+
const items = materializeIterable(props.items());
|
|
810
2030
|
const keys = items.map((item, index) => keyedRowIdentity(props.rowKey(item, index)));
|
|
811
2031
|
if (new Set(keys).size !== keys.length) return null;
|
|
812
2032
|
return { items, keys };
|
|
813
2033
|
}
|
|
2034
|
+
usesDelegatedEvents(props = this.currentProps) {
|
|
2035
|
+
return Boolean(
|
|
2036
|
+
props.delegateEvents && props.events?.length && props.events.every((event) => event.path !== void 0)
|
|
2037
|
+
);
|
|
2038
|
+
}
|
|
2039
|
+
rebuildElementIndex(instances) {
|
|
2040
|
+
this.instancesByElement = /* @__PURE__ */ new WeakMap();
|
|
2041
|
+
for (const instance of instances.values()) {
|
|
2042
|
+
this.instancesByElement.set(instance.element, instance);
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
2045
|
+
eventRowInstance(event) {
|
|
2046
|
+
if (!this.root) return void 0;
|
|
2047
|
+
const target = event.target;
|
|
2048
|
+
if (!target) return void 0;
|
|
2049
|
+
let element = target.nodeType === 1 ? target : target.parentElement;
|
|
2050
|
+
while (element && element.parentElement !== this.root) element = element.parentElement;
|
|
2051
|
+
return element?.parentElement === this.root ? this.instancesByElement.get(element) : void 0;
|
|
2052
|
+
}
|
|
2053
|
+
invokeDelegatedEvent(descriptor, instance, event, currentTarget) {
|
|
2054
|
+
const ownCurrentTarget = Object.getOwnPropertyDescriptor(event, "currentTarget");
|
|
2055
|
+
try {
|
|
2056
|
+
Object.defineProperty(event, "currentTarget", {
|
|
2057
|
+
configurable: true,
|
|
2058
|
+
value: currentTarget
|
|
2059
|
+
});
|
|
2060
|
+
descriptor.invoke(instance.item, instance.index, event);
|
|
2061
|
+
} finally {
|
|
2062
|
+
if (ownCurrentTarget) Object.defineProperty(event, "currentTarget", ownCurrentTarget);
|
|
2063
|
+
else Reflect.deleteProperty(event, "currentTarget");
|
|
2064
|
+
}
|
|
2065
|
+
}
|
|
2066
|
+
delegatedContainerProps(container) {
|
|
2067
|
+
if (this.state.fallback || !this.usesDelegatedEvents()) return {};
|
|
2068
|
+
const props = container.props;
|
|
2069
|
+
return Object.fromEntries(
|
|
2070
|
+
[...new Set((this.currentProps.events || []).map((event) => event.name))].map((name) => {
|
|
2071
|
+
const existing = props[name];
|
|
2072
|
+
const capture = name.endsWith("Capture");
|
|
2073
|
+
const handler = (event) => {
|
|
2074
|
+
if (capture) existing?.(event);
|
|
2075
|
+
if (!event.isPropagationStopped()) this.dispatchDelegatedEvent(name, event);
|
|
2076
|
+
if (!capture && !event.isPropagationStopped()) existing?.(event);
|
|
2077
|
+
};
|
|
2078
|
+
return [name, handler];
|
|
2079
|
+
})
|
|
2080
|
+
);
|
|
2081
|
+
}
|
|
814
2082
|
subscribeToRowConditional(key, id, refresh) {
|
|
815
2083
|
let listeners = this.conditionalListeners.get(key);
|
|
816
2084
|
if (!listeners) {
|
|
@@ -826,7 +2094,19 @@ function createKeyedRowsBlockComponent(owner) {
|
|
|
826
2094
|
};
|
|
827
2095
|
}
|
|
828
2096
|
hasReactOwnedRows(props = this.currentProps) {
|
|
829
|
-
return Boolean(
|
|
2097
|
+
return Boolean(
|
|
2098
|
+
props.conditionals?.length || props.events?.length && !this.usesDelegatedEvents(props)
|
|
2099
|
+
);
|
|
2100
|
+
}
|
|
2101
|
+
cleanupHostScopes(instances = this.instances) {
|
|
2102
|
+
for (const instance of instances.values()) instance.scope?.cleanup();
|
|
2103
|
+
}
|
|
2104
|
+
mountRowHostScope(element, descriptor, props = this.currentProps) {
|
|
2105
|
+
if (!props.hostBlocks) return void 0;
|
|
2106
|
+
return options.hostBlocks?.mount(element, descriptor, this.requestHostScopeFallback) || null;
|
|
2107
|
+
}
|
|
2108
|
+
readConditionalValues(props, item, index) {
|
|
2109
|
+
return options.conditionals?.readValues(props, item, index) || EMPTY_KEYED_ROW_CONDITIONAL_VALUES;
|
|
830
2110
|
}
|
|
831
2111
|
pruneEventHandlers(keys) {
|
|
832
2112
|
const active = new Set(keys);
|
|
@@ -850,20 +2130,24 @@ function createKeyedRowsBlockComponent(owner) {
|
|
|
850
2130
|
);
|
|
851
2131
|
const instances = /* @__PURE__ */ new Map();
|
|
852
2132
|
for (let index = 0; index < rows.items.length; index += 1) {
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
this.
|
|
856
|
-
|
|
857
|
-
|
|
2133
|
+
const descriptor = this.currentProps.create(rows.items[index], index);
|
|
2134
|
+
if (this.hasReactOwnedRows() && !matchesCompilerHostElement(elements[index], descriptor, opaqueConditionalPaths)) {
|
|
2135
|
+
this.cleanupHostScopes(instances);
|
|
2136
|
+
return false;
|
|
2137
|
+
}
|
|
2138
|
+
const scope = this.mountRowHostScope(elements[index], descriptor);
|
|
2139
|
+
if (this.currentProps.hostBlocks && !scope) {
|
|
2140
|
+
this.cleanupHostScopes(instances);
|
|
858
2141
|
return false;
|
|
859
2142
|
}
|
|
860
2143
|
const instance = {
|
|
861
2144
|
key: rows.keys[index],
|
|
862
2145
|
element: elements[index],
|
|
2146
|
+
scope: scope || void 0,
|
|
863
2147
|
values: this.hasReactOwnedRows() ? this.currentProps.bindings.map(() => UNSET_KEYED_ROW_BINDING) : readKeyedRowBindingValues(this.currentProps, rows.items[index], index),
|
|
864
2148
|
item: rows.items[index],
|
|
865
2149
|
index,
|
|
866
|
-
conditionalValues:
|
|
2150
|
+
conditionalValues: this.readConditionalValues(
|
|
867
2151
|
this.currentProps,
|
|
868
2152
|
rows.items[index],
|
|
869
2153
|
index
|
|
@@ -874,7 +2158,9 @@ function createKeyedRowsBlockComponent(owner) {
|
|
|
874
2158
|
}
|
|
875
2159
|
instances.set(rows.keys[index], instance);
|
|
876
2160
|
}
|
|
2161
|
+
this.cleanupHostScopes();
|
|
877
2162
|
this.instances = instances;
|
|
2163
|
+
this.rebuildElementIndex(instances);
|
|
878
2164
|
this.pruneEventHandlers(rows.keys);
|
|
879
2165
|
this.pruneConditionalListeners(rows.keys);
|
|
880
2166
|
return true;
|
|
@@ -893,6 +2179,7 @@ function createKeyedRowsBlockComponent(owner) {
|
|
|
893
2179
|
}
|
|
894
2180
|
this.fallbackRequested = true;
|
|
895
2181
|
this.fallbackKeysWereUnsafe = this.hasUnsafeFallbackKeys();
|
|
2182
|
+
this.cleanupHostScopes();
|
|
896
2183
|
this.fallbackVersion += 1;
|
|
897
2184
|
this.setState({ fallback: true }, afterCommit);
|
|
898
2185
|
}
|
|
@@ -927,6 +2214,116 @@ function createKeyedRowsBlockComponent(owner) {
|
|
|
927
2214
|
}
|
|
928
2215
|
});
|
|
929
2216
|
}
|
|
2217
|
+
refreshDirtyBindings(dirtyState, afterCommit) {
|
|
2218
|
+
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)) {
|
|
2219
|
+
return false;
|
|
2220
|
+
}
|
|
2221
|
+
const affectedBindingIndices = [];
|
|
2222
|
+
for (let bindingIndex = 0; bindingIndex < this.currentProps.bindings.length; bindingIndex += 1) {
|
|
2223
|
+
const dependencies = this.currentProps.bindings[bindingIndex].dependencies || [];
|
|
2224
|
+
if (dependencies.some((dependency) => dirtyState.has(dependency))) {
|
|
2225
|
+
affectedBindingIndices.push(bindingIndex);
|
|
2226
|
+
}
|
|
2227
|
+
}
|
|
2228
|
+
for (const instance of this.instances.values()) {
|
|
2229
|
+
for (const bindingIndex of affectedBindingIndices) {
|
|
2230
|
+
applyKeyedRowBinding(
|
|
2231
|
+
this.currentProps,
|
|
2232
|
+
instance,
|
|
2233
|
+
instance.item,
|
|
2234
|
+
instance.index,
|
|
2235
|
+
bindingIndex
|
|
2236
|
+
);
|
|
2237
|
+
}
|
|
2238
|
+
}
|
|
2239
|
+
afterCommit?.();
|
|
2240
|
+
return true;
|
|
2241
|
+
}
|
|
2242
|
+
reconcileStableRows(rows, afterCommit) {
|
|
2243
|
+
if (rows.keys.length !== this.instances.size) return false;
|
|
2244
|
+
let index = 0;
|
|
2245
|
+
for (const key of this.instances.keys()) {
|
|
2246
|
+
if (rows.keys[index] !== key) return false;
|
|
2247
|
+
index += 1;
|
|
2248
|
+
}
|
|
2249
|
+
const conditionalChanges = [];
|
|
2250
|
+
for (index = 0; index < rows.items.length; index += 1) {
|
|
2251
|
+
const key = rows.keys[index];
|
|
2252
|
+
const existing = this.instances.get(key);
|
|
2253
|
+
if (!existing) return false;
|
|
2254
|
+
if (this.currentProps.hostBlocks) {
|
|
2255
|
+
const descriptor = this.currentProps.create(rows.items[index], index);
|
|
2256
|
+
if (!existing.scope?.update(descriptor)) {
|
|
2257
|
+
this.activateFallback(afterCommit);
|
|
2258
|
+
return true;
|
|
2259
|
+
}
|
|
2260
|
+
}
|
|
2261
|
+
applyKeyedRowBindings(this.currentProps, existing, rows.items[index], index);
|
|
2262
|
+
const conditionalValues = this.readConditionalValues(
|
|
2263
|
+
this.currentProps,
|
|
2264
|
+
rows.items[index],
|
|
2265
|
+
index
|
|
2266
|
+
);
|
|
2267
|
+
for (const [id, values] of conditionalValues) {
|
|
2268
|
+
if (options.conditionals?.changed(existing.conditionalValues.get(id), values)) {
|
|
2269
|
+
conditionalChanges.push({ key, id, item: rows.items[index], index });
|
|
2270
|
+
}
|
|
2271
|
+
}
|
|
2272
|
+
existing.conditionalValues = conditionalValues;
|
|
2273
|
+
existing.item = rows.items[index];
|
|
2274
|
+
existing.index = index;
|
|
2275
|
+
}
|
|
2276
|
+
this.notifyConditionalChanges(conditionalChanges, afterCommit);
|
|
2277
|
+
return true;
|
|
2278
|
+
}
|
|
2279
|
+
reconcileSingleRemoval(rows, afterCommit) {
|
|
2280
|
+
if (this.hasReactOwnedRows() || rows.keys.length + 1 !== this.instances.size) return false;
|
|
2281
|
+
const previousKeys = [...this.instances.keys()];
|
|
2282
|
+
let removedIndex = 0;
|
|
2283
|
+
while (removedIndex < rows.keys.length && previousKeys[removedIndex] === rows.keys[removedIndex]) {
|
|
2284
|
+
removedIndex += 1;
|
|
2285
|
+
}
|
|
2286
|
+
for (let index = removedIndex; index < rows.keys.length; index += 1) {
|
|
2287
|
+
if (previousKeys[index + 1] !== rows.keys[index]) return false;
|
|
2288
|
+
}
|
|
2289
|
+
const removedKey = previousKeys[removedIndex];
|
|
2290
|
+
const removed = this.instances.get(removedKey);
|
|
2291
|
+
if (!removed) return false;
|
|
2292
|
+
const conditionalChanges = [];
|
|
2293
|
+
for (let index = 0; index < rows.items.length; index += 1) {
|
|
2294
|
+
const key = rows.keys[index];
|
|
2295
|
+
const existing = this.instances.get(key);
|
|
2296
|
+
if (!existing) return false;
|
|
2297
|
+
if (this.currentProps.hostBlocks) {
|
|
2298
|
+
const descriptor = this.currentProps.create(rows.items[index], index);
|
|
2299
|
+
if (!existing.scope?.update(descriptor)) {
|
|
2300
|
+
this.activateFallback(afterCommit);
|
|
2301
|
+
return true;
|
|
2302
|
+
}
|
|
2303
|
+
}
|
|
2304
|
+
applyKeyedRowBindings(this.currentProps, existing, rows.items[index], index);
|
|
2305
|
+
const conditionalValues = this.readConditionalValues(
|
|
2306
|
+
this.currentProps,
|
|
2307
|
+
rows.items[index],
|
|
2308
|
+
index
|
|
2309
|
+
);
|
|
2310
|
+
for (const [id, values] of conditionalValues) {
|
|
2311
|
+
if (options.conditionals?.changed(existing.conditionalValues.get(id), values)) {
|
|
2312
|
+
conditionalChanges.push({ key, id, item: rows.items[index], index });
|
|
2313
|
+
}
|
|
2314
|
+
}
|
|
2315
|
+
existing.conditionalValues = conditionalValues;
|
|
2316
|
+
existing.item = rows.items[index];
|
|
2317
|
+
existing.index = index;
|
|
2318
|
+
}
|
|
2319
|
+
removed.scope?.cleanup();
|
|
2320
|
+
removed.element.remove();
|
|
2321
|
+
this.instances.delete(removedKey);
|
|
2322
|
+
this.eventHandlers.delete(removedKey);
|
|
2323
|
+
this.conditionalListeners.delete(removedKey);
|
|
2324
|
+
this.notifyConditionalChanges(conditionalChanges, afterCommit);
|
|
2325
|
+
return true;
|
|
2326
|
+
}
|
|
930
2327
|
reconcile(afterCommit) {
|
|
931
2328
|
if (!this.mounted || !this.root) {
|
|
932
2329
|
afterCommit?.();
|
|
@@ -946,35 +2343,62 @@ function createKeyedRowsBlockComponent(owner) {
|
|
|
946
2343
|
this.activateFallback(afterCommit);
|
|
947
2344
|
return;
|
|
948
2345
|
}
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
2346
|
+
if (this.hasReactOwnedRows()) {
|
|
2347
|
+
const previousKeys = [...this.instances.keys()];
|
|
2348
|
+
if (rows.keys.length !== previousKeys.length || rows.keys.some((key, index) => key !== previousKeys[index])) {
|
|
2349
|
+
this.synchronizeReactOwnedRows(afterCommit);
|
|
2350
|
+
return;
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
if (rows.items.length === 0) {
|
|
2354
|
+
this.cleanupHostScopes();
|
|
2355
|
+
this.root.replaceChildren();
|
|
2356
|
+
this.instances = /* @__PURE__ */ new Map();
|
|
2357
|
+
this.instancesByElement = /* @__PURE__ */ new WeakMap();
|
|
2358
|
+
this.eventHandlers.clear();
|
|
2359
|
+
this.conditionalListeners.clear();
|
|
2360
|
+
afterCommit?.();
|
|
952
2361
|
return;
|
|
953
2362
|
}
|
|
954
|
-
|
|
2363
|
+
if (this.reconcileStableRows(rows, afterCommit)) return;
|
|
2364
|
+
if (this.reconcileSingleRemoval(rows, afterCommit)) return;
|
|
955
2365
|
const activeElement = this.root.ownerDocument.activeElement;
|
|
956
2366
|
const restoreFocus = Boolean(activeElement && this.root.contains(activeElement));
|
|
957
|
-
[...this.instances].forEach(([key], index) => oldIndices.set(key, index));
|
|
958
2367
|
const nextKeys = new Set(rows.keys);
|
|
2368
|
+
const hasSurvivingRows = rows.keys.some((key) => this.instances.has(key));
|
|
2369
|
+
const oldIndices = /* @__PURE__ */ new Map();
|
|
2370
|
+
if (hasSurvivingRows) {
|
|
2371
|
+
[...this.instances].forEach(([key], index) => oldIndices.set(key, index));
|
|
2372
|
+
}
|
|
959
2373
|
for (const [key, instance] of this.instances) {
|
|
960
|
-
if (!nextKeys.has(key))
|
|
2374
|
+
if (!nextKeys.has(key)) {
|
|
2375
|
+
instance.scope?.cleanup();
|
|
2376
|
+
if (hasSurvivingRows) instance.element.remove();
|
|
2377
|
+
}
|
|
961
2378
|
}
|
|
962
|
-
const sequence = rows.keys.map((key) => oldIndices.get(key) ?? -1);
|
|
963
|
-
const stablePositions = longestIncreasingSubsequencePositions(sequence);
|
|
2379
|
+
const sequence = hasSurvivingRows ? rows.keys.map((key) => oldIndices.get(key) ?? -1) : rows.keys.map(() => -1);
|
|
2380
|
+
const stablePositions = hasSurvivingRows ? longestIncreasingSubsequencePositions(sequence) : /* @__PURE__ */ new Set();
|
|
964
2381
|
const nextInstances = [];
|
|
965
2382
|
const conditionalChanges = [];
|
|
966
2383
|
for (let index = 0; index < rows.items.length; index += 1) {
|
|
967
2384
|
const key = rows.keys[index];
|
|
968
2385
|
const existing = this.instances.get(key);
|
|
969
2386
|
if (existing) {
|
|
2387
|
+
if (this.currentProps.hostBlocks) {
|
|
2388
|
+
const descriptor2 = this.currentProps.create(rows.items[index], index);
|
|
2389
|
+
if (!existing.scope?.update(descriptor2)) {
|
|
2390
|
+
this.activateFallback(afterCommit);
|
|
2391
|
+
return;
|
|
2392
|
+
}
|
|
2393
|
+
}
|
|
970
2394
|
applyKeyedRowBindings(this.currentProps, existing, rows.items[index], index);
|
|
971
|
-
const conditionalValues =
|
|
2395
|
+
const conditionalValues = this.readConditionalValues(
|
|
972
2396
|
this.currentProps,
|
|
973
2397
|
rows.items[index],
|
|
974
2398
|
index
|
|
975
2399
|
);
|
|
976
2400
|
for (const [id, values] of conditionalValues) {
|
|
977
|
-
if (
|
|
2401
|
+
if (options.conditionals?.changed(existing.conditionalValues.get(id), values)) {
|
|
978
2402
|
conditionalChanges.push({ key, id, item: rows.items[index], index });
|
|
979
2403
|
}
|
|
980
2404
|
}
|
|
@@ -984,34 +2408,58 @@ function createKeyedRowsBlockComponent(owner) {
|
|
|
984
2408
|
nextInstances.push(existing);
|
|
985
2409
|
continue;
|
|
986
2410
|
}
|
|
987
|
-
const
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
)
|
|
2411
|
+
const descriptor = this.currentProps.create(rows.items[index], index);
|
|
2412
|
+
const element = createCompilerHostElement(this.root.ownerDocument, descriptor);
|
|
2413
|
+
const scope = this.mountRowHostScope(element, descriptor);
|
|
2414
|
+
if (this.currentProps.hostBlocks && !scope) {
|
|
2415
|
+
for (const instance of nextInstances) {
|
|
2416
|
+
if (!this.instances.has(instance.key)) instance.scope?.cleanup();
|
|
2417
|
+
}
|
|
2418
|
+
this.activateFallback(afterCommit);
|
|
2419
|
+
return;
|
|
2420
|
+
}
|
|
991
2421
|
nextInstances.push({
|
|
992
2422
|
key,
|
|
993
2423
|
element,
|
|
2424
|
+
scope: scope || void 0,
|
|
994
2425
|
values: readKeyedRowBindingValues(this.currentProps, rows.items[index], index),
|
|
995
2426
|
item: rows.items[index],
|
|
996
2427
|
index,
|
|
997
|
-
conditionalValues:
|
|
2428
|
+
conditionalValues: this.readConditionalValues(
|
|
998
2429
|
this.currentProps,
|
|
999
2430
|
rows.items[index],
|
|
1000
2431
|
index
|
|
1001
2432
|
)
|
|
1002
2433
|
});
|
|
1003
2434
|
}
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
const instance
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
2435
|
+
if (!hasSurvivingRows) {
|
|
2436
|
+
const fragment = this.root.ownerDocument.createDocumentFragment();
|
|
2437
|
+
for (const instance of nextInstances) fragment.append(instance.element);
|
|
2438
|
+
this.root.replaceChildren(fragment);
|
|
2439
|
+
} else {
|
|
2440
|
+
let anchor = null;
|
|
2441
|
+
for (let index = nextInstances.length - 1; index >= 0; index -= 1) {
|
|
2442
|
+
const instance = nextInstances[index];
|
|
2443
|
+
if (sequence[index] < 0) {
|
|
2444
|
+
let start = index;
|
|
2445
|
+
while (start > 0 && sequence[start - 1] < 0) start -= 1;
|
|
2446
|
+
const fragment = this.root.ownerDocument.createDocumentFragment();
|
|
2447
|
+
for (let itemIndex = start; itemIndex <= index; itemIndex += 1) {
|
|
2448
|
+
fragment.append(nextInstances[itemIndex].element);
|
|
2449
|
+
}
|
|
2450
|
+
this.root.insertBefore(fragment, anchor);
|
|
2451
|
+
anchor = nextInstances[start].element;
|
|
2452
|
+
index = start;
|
|
2453
|
+
} else {
|
|
2454
|
+
if (!stablePositions.has(index) && instance.element.nextSibling !== anchor) {
|
|
2455
|
+
this.root.insertBefore(instance.element, anchor);
|
|
2456
|
+
}
|
|
2457
|
+
anchor = instance.element;
|
|
2458
|
+
}
|
|
1011
2459
|
}
|
|
1012
|
-
anchor = instance.element;
|
|
1013
2460
|
}
|
|
1014
2461
|
this.instances = new Map(nextInstances.map((instance) => [instance.key, instance]));
|
|
2462
|
+
this.rebuildElementIndex(this.instances);
|
|
1015
2463
|
this.pruneEventHandlers(rows.keys);
|
|
1016
2464
|
this.pruneConditionalListeners(rows.keys);
|
|
1017
2465
|
if (restoreFocus && activeElement?.isConnected && activeElement.ownerDocument.activeElement !== activeElement && "focus" in activeElement) {
|
|
@@ -1054,7 +2502,9 @@ function createKeyedRowsBlockComponent(owner) {
|
|
|
1054
2502
|
this.mounted = false;
|
|
1055
2503
|
this.unsubscribe?.();
|
|
1056
2504
|
this.root = null;
|
|
2505
|
+
this.cleanupHostScopes();
|
|
1057
2506
|
this.instances.clear();
|
|
2507
|
+
this.instancesByElement = /* @__PURE__ */ new WeakMap();
|
|
1058
2508
|
this.eventHandlers.clear();
|
|
1059
2509
|
this.conditionalListeners.clear();
|
|
1060
2510
|
}
|
|
@@ -1067,6 +2517,7 @@ function createKeyedRowsBlockComponent(owner) {
|
|
|
1067
2517
|
);
|
|
1068
2518
|
}
|
|
1069
2519
|
return React.cloneElement(container, {
|
|
2520
|
+
...this.delegatedContainerProps(container),
|
|
1070
2521
|
key: this.state.fallback ? `react-${this.fallbackVersion}` : "compiled",
|
|
1071
2522
|
ref: this.captureRoot
|
|
1072
2523
|
});
|
|
@@ -1088,6 +2539,7 @@ function createKeyedRangesBlockComponent(owner) {
|
|
|
1088
2539
|
this.currentProps = this.props;
|
|
1089
2540
|
this.rangeInstances = [];
|
|
1090
2541
|
this.staticSegments = [];
|
|
2542
|
+
this.staticValues = [];
|
|
1091
2543
|
this.captureRoot = (root) => {
|
|
1092
2544
|
this.root = root;
|
|
1093
2545
|
this.currentProps.rootRef?.(root);
|
|
@@ -1097,8 +2549,7 @@ function createKeyedRangesBlockComponent(owner) {
|
|
|
1097
2549
|
};
|
|
1098
2550
|
}
|
|
1099
2551
|
readRange(range) {
|
|
1100
|
-
const
|
|
1101
|
-
const items = source ? Array.from(source) : [];
|
|
2552
|
+
const items = materializeIterable(range.items());
|
|
1102
2553
|
const keys = items.map((item, index) => keyedRowIdentity(range.rowKey(item, index)));
|
|
1103
2554
|
if (new Set(keys).size !== keys.length) return null;
|
|
1104
2555
|
return { items, keys };
|
|
@@ -1152,6 +2603,11 @@ function createKeyedRangesBlockComponent(owner) {
|
|
|
1152
2603
|
staticSegments.push(elements.slice(cursor));
|
|
1153
2604
|
this.staticSegments = staticSegments;
|
|
1154
2605
|
this.rangeInstances = instancesByRange;
|
|
2606
|
+
if (!applyStaticRangeBindings(props.bindings, this.staticSegments, this.staticValues)) {
|
|
2607
|
+
this.rangeInstances = [];
|
|
2608
|
+
this.staticSegments = [];
|
|
2609
|
+
return false;
|
|
2610
|
+
}
|
|
1155
2611
|
return true;
|
|
1156
2612
|
}
|
|
1157
2613
|
anchorAfter(rangeIndex) {
|
|
@@ -1228,6 +2684,14 @@ function createKeyedRangesBlockComponent(owner) {
|
|
|
1228
2684
|
this.activateFallback(afterCommit);
|
|
1229
2685
|
return;
|
|
1230
2686
|
}
|
|
2687
|
+
if (!applyStaticRangeBindings(
|
|
2688
|
+
this.currentProps.bindings,
|
|
2689
|
+
this.staticSegments,
|
|
2690
|
+
this.staticValues
|
|
2691
|
+
)) {
|
|
2692
|
+
this.activateFallback(afterCommit);
|
|
2693
|
+
return;
|
|
2694
|
+
}
|
|
1231
2695
|
const activeElement = this.root.ownerDocument.activeElement;
|
|
1232
2696
|
const restoreFocus = Boolean(activeElement && this.root.contains(activeElement));
|
|
1233
2697
|
for (let rangeIndex = rowsByRange.length - 1; rangeIndex >= 0; rangeIndex -= 1) {
|
|
@@ -1271,6 +2735,7 @@ function createKeyedRangesBlockComponent(owner) {
|
|
|
1271
2735
|
this.root = null;
|
|
1272
2736
|
this.rangeInstances = [];
|
|
1273
2737
|
this.staticSegments = [];
|
|
2738
|
+
this.staticValues.length = 0;
|
|
1274
2739
|
}
|
|
1275
2740
|
render() {
|
|
1276
2741
|
const container = this.currentProps.render();
|
|
@@ -1288,6 +2753,128 @@ function createKeyedRangesBlockComponent(owner) {
|
|
|
1288
2753
|
FarmKeyedRangesBlock.displayName = "FarmCompiledKeyedRanges";
|
|
1289
2754
|
return FarmKeyedRangesBlock;
|
|
1290
2755
|
}
|
|
2756
|
+
function createMixedRangesBlockComponent(owner) {
|
|
2757
|
+
class FarmMixedRangesBlock extends React.Component {
|
|
2758
|
+
constructor() {
|
|
2759
|
+
super(...arguments);
|
|
2760
|
+
this.state = { fallback: false };
|
|
2761
|
+
this.root = null;
|
|
2762
|
+
this.mounted = false;
|
|
2763
|
+
this.fallbackRequested = false;
|
|
2764
|
+
this.fallbackVersion = 0;
|
|
2765
|
+
this.propFallbackQueued = false;
|
|
2766
|
+
this.currentProps = this.props;
|
|
2767
|
+
this.controller = null;
|
|
2768
|
+
this.fallbackUnsubscribers = [];
|
|
2769
|
+
this.captureRoot = (root) => {
|
|
2770
|
+
this.root = root;
|
|
2771
|
+
this.currentProps.rootRef?.(root);
|
|
2772
|
+
};
|
|
2773
|
+
this.activateFallback = (afterCommit) => {
|
|
2774
|
+
if (!this.mounted || this.state.fallback || this.fallbackRequested) {
|
|
2775
|
+
afterCommit?.();
|
|
2776
|
+
return;
|
|
2777
|
+
}
|
|
2778
|
+
this.fallbackRequested = true;
|
|
2779
|
+
this.controller?.cleanup();
|
|
2780
|
+
this.controller = null;
|
|
2781
|
+
this.fallbackVersion += 1;
|
|
2782
|
+
this.setState({ fallback: true }, () => {
|
|
2783
|
+
this.subscribeFallbackBlocks();
|
|
2784
|
+
afterCommit?.();
|
|
2785
|
+
});
|
|
2786
|
+
};
|
|
2787
|
+
}
|
|
2788
|
+
clearFallbackSubscriptions() {
|
|
2789
|
+
for (const unsubscribe of this.fallbackUnsubscribers) unsubscribe();
|
|
2790
|
+
this.fallbackUnsubscribers = [];
|
|
2791
|
+
}
|
|
2792
|
+
subscribeFallbackBlocks() {
|
|
2793
|
+
this.clearFallbackSubscriptions();
|
|
2794
|
+
const descriptor = this.currentProps.create();
|
|
2795
|
+
const ids = /* @__PURE__ */ new Set();
|
|
2796
|
+
collectCompilerHostBlockIds(descriptor, ids);
|
|
2797
|
+
for (const id of ids) {
|
|
2798
|
+
this.fallbackUnsubscribers.push(
|
|
2799
|
+
owner.subscribe(id, (afterCommit) => {
|
|
2800
|
+
if (!this.mounted || !this.state.fallback) {
|
|
2801
|
+
afterCommit?.();
|
|
2802
|
+
return;
|
|
2803
|
+
}
|
|
2804
|
+
this.fallbackVersion += 1;
|
|
2805
|
+
this.forceUpdate(afterCommit);
|
|
2806
|
+
})
|
|
2807
|
+
);
|
|
2808
|
+
}
|
|
2809
|
+
}
|
|
2810
|
+
adopt() {
|
|
2811
|
+
if (!this.root) return false;
|
|
2812
|
+
const descriptor = this.currentProps.create();
|
|
2813
|
+
const block = descriptor.block;
|
|
2814
|
+
if (block?.kind !== "mixed-ranges" || block.id !== this.currentProps.id) return false;
|
|
2815
|
+
const controller = new CompilerNestedMixedRanges(
|
|
2816
|
+
owner,
|
|
2817
|
+
this.root,
|
|
2818
|
+
descriptor,
|
|
2819
|
+
block,
|
|
2820
|
+
this.activateFallback
|
|
2821
|
+
);
|
|
2822
|
+
try {
|
|
2823
|
+
if (!controller.adopt()) {
|
|
2824
|
+
controller.cleanup();
|
|
2825
|
+
return false;
|
|
2826
|
+
}
|
|
2827
|
+
} catch (error) {
|
|
2828
|
+
controller.cleanup();
|
|
2829
|
+
throw error;
|
|
2830
|
+
}
|
|
2831
|
+
this.controller = controller;
|
|
2832
|
+
return true;
|
|
2833
|
+
}
|
|
2834
|
+
schedulePropFallback() {
|
|
2835
|
+
if (this.propFallbackQueued) return;
|
|
2836
|
+
this.propFallbackQueued = true;
|
|
2837
|
+
queueMicrotask(() => {
|
|
2838
|
+
this.propFallbackQueued = false;
|
|
2839
|
+
if (this.mounted && !this.state.fallback) this.activateFallback();
|
|
2840
|
+
});
|
|
2841
|
+
}
|
|
2842
|
+
shouldComponentUpdate(nextProps, nextState) {
|
|
2843
|
+
this.currentProps = nextProps;
|
|
2844
|
+
if (nextState.fallback || this.state.fallback) return true;
|
|
2845
|
+
this.schedulePropFallback();
|
|
2846
|
+
return false;
|
|
2847
|
+
}
|
|
2848
|
+
componentDidMount() {
|
|
2849
|
+
this.mounted = true;
|
|
2850
|
+
if (!this.adopt()) this.activateFallback();
|
|
2851
|
+
}
|
|
2852
|
+
componentDidUpdate() {
|
|
2853
|
+
if (this.state.fallback) this.subscribeFallbackBlocks();
|
|
2854
|
+
}
|
|
2855
|
+
componentWillUnmount() {
|
|
2856
|
+
this.mounted = false;
|
|
2857
|
+
this.controller?.cleanup();
|
|
2858
|
+
this.controller = null;
|
|
2859
|
+
this.clearFallbackSubscriptions();
|
|
2860
|
+
this.root = null;
|
|
2861
|
+
}
|
|
2862
|
+
render() {
|
|
2863
|
+
const container = this.currentProps.render();
|
|
2864
|
+
if (!React.isValidElement(container) || typeof container.type !== "string") {
|
|
2865
|
+
throw new TypeError(
|
|
2866
|
+
`Compiled mixed ranges ${this.currentProps.id} must own one host container.`
|
|
2867
|
+
);
|
|
2868
|
+
}
|
|
2869
|
+
return React.cloneElement(container, {
|
|
2870
|
+
key: this.state.fallback ? `react-${this.fallbackVersion}` : "compiled",
|
|
2871
|
+
ref: this.captureRoot
|
|
2872
|
+
});
|
|
2873
|
+
}
|
|
2874
|
+
}
|
|
2875
|
+
FarmMixedRangesBlock.displayName = "FarmCompiledMixedRanges";
|
|
2876
|
+
return FarmMixedRangesBlock;
|
|
2877
|
+
}
|
|
1291
2878
|
function createComponentBlockComponent(owner) {
|
|
1292
2879
|
class FarmComponentBlock extends React.Component {
|
|
1293
2880
|
constructor() {
|
|
@@ -1317,12 +2904,86 @@ function createComponentBlockComponent(owner) {
|
|
|
1317
2904
|
FarmComponentBlock.displayName = "FarmCompiledComponentIsland";
|
|
1318
2905
|
return FarmComponentBlock;
|
|
1319
2906
|
}
|
|
1320
|
-
|
|
2907
|
+
var conditionalRuntimeFeature = {
|
|
2908
|
+
name: "conditional",
|
|
2909
|
+
create: (owner) => ({
|
|
2910
|
+
Conditional: createConditionalBlockComponent(owner)
|
|
2911
|
+
})
|
|
2912
|
+
};
|
|
2913
|
+
var hostConditionalRuntimeFeature = {
|
|
2914
|
+
name: "host-conditional",
|
|
2915
|
+
create: (owner) => ({
|
|
2916
|
+
HostConditional: createHostConditionalBlockComponent(owner)
|
|
2917
|
+
})
|
|
2918
|
+
};
|
|
2919
|
+
var conditionalRangesRuntimeFeature = {
|
|
2920
|
+
name: "conditional-ranges",
|
|
2921
|
+
create: (owner) => ({
|
|
2922
|
+
ConditionalRanges: createConditionalRangesBlockComponent(owner)
|
|
2923
|
+
})
|
|
2924
|
+
};
|
|
2925
|
+
var keyedListRuntimeFeature = {
|
|
2926
|
+
name: "keyed-list",
|
|
2927
|
+
create: (owner) => ({
|
|
2928
|
+
KeyedList: createKeyedListBlockComponent(owner)
|
|
2929
|
+
})
|
|
2930
|
+
};
|
|
2931
|
+
var keyedRowsRuntimeFeature = {
|
|
2932
|
+
name: "keyed-rows",
|
|
2933
|
+
create: (owner) => ({
|
|
2934
|
+
KeyedRows: createKeyedRowsBlockComponent(owner)
|
|
2935
|
+
})
|
|
2936
|
+
};
|
|
2937
|
+
var keyedRowsConditionalRuntimeFeature = {
|
|
2938
|
+
name: "keyed-rows:conditional",
|
|
2939
|
+
create: (owner) => ({
|
|
2940
|
+
KeyedRows: createKeyedRowsBlockComponent(owner, {
|
|
2941
|
+
conditionals: createKeyedRowConditionalRuntime()
|
|
2942
|
+
})
|
|
2943
|
+
})
|
|
2944
|
+
};
|
|
2945
|
+
var keyedRowsHostRuntimeFeature = {
|
|
2946
|
+
name: "keyed-rows:host",
|
|
2947
|
+
create: (owner) => ({
|
|
2948
|
+
KeyedRows: createKeyedRowsBlockComponent(owner, {
|
|
2949
|
+
hostBlocks: createKeyedRowHostRuntime()
|
|
2950
|
+
})
|
|
2951
|
+
})
|
|
2952
|
+
};
|
|
2953
|
+
var keyedRowsCompleteRuntimeFeature = {
|
|
2954
|
+
name: "keyed-rows:complete",
|
|
2955
|
+
create: (owner) => ({
|
|
2956
|
+
KeyedRows: createKeyedRowsBlockComponent(owner, {
|
|
2957
|
+
conditionals: createKeyedRowConditionalRuntime(),
|
|
2958
|
+
hostBlocks: createKeyedRowHostRuntime()
|
|
2959
|
+
})
|
|
2960
|
+
})
|
|
2961
|
+
};
|
|
2962
|
+
var keyedRangesRuntimeFeature = {
|
|
2963
|
+
name: "keyed-ranges",
|
|
2964
|
+
create: (owner) => ({
|
|
2965
|
+
KeyedRanges: createKeyedRangesBlockComponent(owner)
|
|
2966
|
+
})
|
|
2967
|
+
};
|
|
2968
|
+
var mixedRangesRuntimeFeature = {
|
|
2969
|
+
name: "mixed-ranges",
|
|
2970
|
+
create: (owner) => ({
|
|
2971
|
+
MixedRanges: createMixedRangesBlockComponent(owner)
|
|
2972
|
+
})
|
|
2973
|
+
};
|
|
2974
|
+
var componentRuntimeFeature = {
|
|
2975
|
+
name: "component",
|
|
2976
|
+
create: (owner) => ({
|
|
2977
|
+
Component: createComponentBlockComponent(owner)
|
|
2978
|
+
})
|
|
2979
|
+
};
|
|
2980
|
+
function createCompiledComponentWithFeatures(definition, runtimeFeatures) {
|
|
1321
2981
|
const stateSignature = definition.stateSignature || String(definition.initialize.length);
|
|
2982
|
+
const runtimeSignature = [...new Set(runtimeFeatures.map((feature) => feature.name))].sort().join(",");
|
|
1322
2983
|
if (definition.hmrId) {
|
|
1323
2984
|
const registry = getCompilerHmrRegistry();
|
|
1324
2985
|
const existing = registry.get(definition.hmrId);
|
|
1325
|
-
if (existing?.stateSignature === stateSignature) {
|
|
2986
|
+
if (existing?.stateSignature === stateSignature && existing.runtimeSignature === runtimeSignature) {
|
|
1326
2987
|
existing.definition.current = definition;
|
|
1327
2988
|
existing.component.displayName = `FarmCompiled(${definition.displayName})`;
|
|
1328
2989
|
for (const refresh of existing.refreshListeners) refresh();
|
|
@@ -1340,6 +3001,17 @@ function createCompiledComponent(definition) {
|
|
|
1340
3001
|
this.hasBindingError = false;
|
|
1341
3002
|
this.inputSelection = null;
|
|
1342
3003
|
this.dirtyState = /* @__PURE__ */ new Set();
|
|
3004
|
+
this.indexedDefinition = null;
|
|
3005
|
+
this.staticBindingsByDependency = [];
|
|
3006
|
+
this.blockBindingsByDependency = [];
|
|
3007
|
+
this.blockBindings = /* @__PURE__ */ new Map();
|
|
3008
|
+
this.trackedBindingsByDependency = [];
|
|
3009
|
+
this.trackedDependenciesByBinding = /* @__PURE__ */ new Map();
|
|
3010
|
+
this.bindingValues = /* @__PURE__ */ new Map();
|
|
3011
|
+
this.activeBinding = null;
|
|
3012
|
+
this.activeDependencies = null;
|
|
3013
|
+
this.renderedDefinition = null;
|
|
3014
|
+
this.renderedElement = null;
|
|
1343
3015
|
this.blockRefreshListeners = /* @__PURE__ */ new Map();
|
|
1344
3016
|
this.blockRoots = /* @__PURE__ */ new Map();
|
|
1345
3017
|
this.blockRootElements = /* @__PURE__ */ new Set();
|
|
@@ -1351,50 +3023,149 @@ function createCompiledComponent(definition) {
|
|
|
1351
3023
|
this.refreshDefinition = () => {
|
|
1352
3024
|
if (this.mounted) this.forceUpdate();
|
|
1353
3025
|
};
|
|
1354
|
-
|
|
3026
|
+
const initialState = definitionReference.current.initialize(props);
|
|
3027
|
+
const initialProps = definitionReference.current.readProps?.(props) || [];
|
|
3028
|
+
this.propCellOffset = initialState.length;
|
|
3029
|
+
this.cells = [...initialState, ...initialProps].map((initialValue, index) => {
|
|
1355
3030
|
let value = initialValue;
|
|
1356
3031
|
const pending = [];
|
|
1357
3032
|
return {
|
|
1358
|
-
get: () =>
|
|
3033
|
+
get: () => {
|
|
3034
|
+
if (this.activeBinding && this.activeDependencies) {
|
|
3035
|
+
this.activeDependencies.add(index);
|
|
3036
|
+
}
|
|
3037
|
+
return value;
|
|
3038
|
+
},
|
|
1359
3039
|
set: (next) => {
|
|
1360
|
-
pending.push(next);
|
|
3040
|
+
pending.push({ kind: "state", update: next });
|
|
1361
3041
|
this.scheduleBindingFlush(index);
|
|
1362
3042
|
},
|
|
3043
|
+
replace: (next) => {
|
|
3044
|
+
pending.push({ kind: "value", value: next });
|
|
3045
|
+
},
|
|
1363
3046
|
flush: () => {
|
|
1364
3047
|
if (pending.length === 0) return false;
|
|
1365
3048
|
const previous = value;
|
|
1366
3049
|
for (const next of pending.splice(0)) {
|
|
1367
|
-
|
|
3050
|
+
if (next.kind === "value") {
|
|
3051
|
+
value = next.value;
|
|
3052
|
+
} else {
|
|
3053
|
+
value = typeof next.update === "function" ? next.update(value) : next.update;
|
|
3054
|
+
}
|
|
1368
3055
|
}
|
|
1369
3056
|
return !Object.is(previous, value);
|
|
1370
3057
|
}
|
|
1371
3058
|
};
|
|
1372
3059
|
});
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
HostConditional: createHostConditionalBlockComponent({
|
|
1379
|
-
subscribe: (id, refresh) => this.subscribeToBlock(id, refresh)
|
|
1380
|
-
}),
|
|
1381
|
-
ConditionalRanges: createConditionalRangesBlockComponent({
|
|
1382
|
-
subscribe: (id, refresh) => this.subscribeToBlock(id, refresh)
|
|
1383
|
-
}),
|
|
1384
|
-
KeyedList: createKeyedListBlockComponent({
|
|
1385
|
-
subscribe: (id, refresh) => this.subscribeToBlock(id, refresh)
|
|
1386
|
-
}),
|
|
1387
|
-
KeyedRows: createKeyedRowsBlockComponent({
|
|
1388
|
-
subscribe: (id, refresh) => this.subscribeToBlock(id, refresh)
|
|
1389
|
-
}),
|
|
1390
|
-
KeyedRanges: createKeyedRangesBlockComponent({
|
|
1391
|
-
subscribe: (id, refresh) => this.subscribeToBlock(id, refresh)
|
|
1392
|
-
}),
|
|
1393
|
-
Component: createComponentBlockComponent({
|
|
1394
|
-
subscribe: (id, refresh) => this.subscribeToBlock(id, refresh)
|
|
1395
|
-
}),
|
|
3060
|
+
const featureOwner = {
|
|
3061
|
+
setRoot: (id, root) => this.setBlockRoot(id, root),
|
|
3062
|
+
subscribe: (id, refresh) => this.subscribeToBlock(id, refresh)
|
|
3063
|
+
};
|
|
3064
|
+
const blockRuntime = {
|
|
1396
3065
|
target: (id) => this.bindingTarget(id)
|
|
1397
3066
|
};
|
|
3067
|
+
for (const feature of runtimeFeatures) {
|
|
3068
|
+
Object.assign(blockRuntime, feature.create(featureOwner));
|
|
3069
|
+
}
|
|
3070
|
+
this.blockRuntime = blockRuntime;
|
|
3071
|
+
}
|
|
3072
|
+
usesHybridReactivity() {
|
|
3073
|
+
return definitionReference.current.reactivity === "hybrid";
|
|
3074
|
+
}
|
|
3075
|
+
canReuseRenderedElement(currentDefinition, propValues) {
|
|
3076
|
+
return Boolean(
|
|
3077
|
+
this.mounted && propValues && propValues.every(isCompilerPrimitive) && this.renderedDefinition === currentDefinition && this.renderedElement
|
|
3078
|
+
);
|
|
3079
|
+
}
|
|
3080
|
+
renderCellsForProps(propValues) {
|
|
3081
|
+
if (!propValues) return { cells: this.cells, commit: () => void 0 };
|
|
3082
|
+
let committed = false;
|
|
3083
|
+
const cells = this.cells.slice(0, this.propCellOffset);
|
|
3084
|
+
for (let propIndex = 0; propIndex < propValues.length; propIndex += 1) {
|
|
3085
|
+
const cell = this.cells[this.propCellOffset + propIndex];
|
|
3086
|
+
if (!cell) continue;
|
|
3087
|
+
cells.push({
|
|
3088
|
+
get: () => committed ? cell.get() : propValues[propIndex],
|
|
3089
|
+
set: (next) => cell.set(next)
|
|
3090
|
+
});
|
|
3091
|
+
}
|
|
3092
|
+
return {
|
|
3093
|
+
cells,
|
|
3094
|
+
commit: () => {
|
|
3095
|
+
committed = true;
|
|
3096
|
+
}
|
|
3097
|
+
};
|
|
3098
|
+
}
|
|
3099
|
+
tracksBinding(binding) {
|
|
3100
|
+
return this.usesHybridReactivity() && binding.tracking === "dynamic";
|
|
3101
|
+
}
|
|
3102
|
+
ensureBindingIndex() {
|
|
3103
|
+
const currentDefinition = definitionReference.current;
|
|
3104
|
+
if (this.indexedDefinition === currentDefinition) return;
|
|
3105
|
+
this.indexedDefinition = currentDefinition;
|
|
3106
|
+
this.staticBindingsByDependency = Array.from({ length: this.cells.length }, () => []);
|
|
3107
|
+
this.blockBindingsByDependency = Array.from({ length: this.cells.length }, () => []);
|
|
3108
|
+
this.trackedBindingsByDependency = Array.from(
|
|
3109
|
+
{ length: this.cells.length },
|
|
3110
|
+
() => /* @__PURE__ */ new Set()
|
|
3111
|
+
);
|
|
3112
|
+
this.blockBindings.clear();
|
|
3113
|
+
this.trackedDependenciesByBinding.clear();
|
|
3114
|
+
this.bindingValues.clear();
|
|
3115
|
+
for (const binding of currentDefinition.bindings) {
|
|
3116
|
+
if (binding.kind === "block") this.blockBindings.set(binding.id, binding);
|
|
3117
|
+
for (const dependency of binding.dependencies) {
|
|
3118
|
+
if (dependency < 0 || dependency >= this.cells.length) continue;
|
|
3119
|
+
if (binding.kind === "block") {
|
|
3120
|
+
this.blockBindingsByDependency[dependency].push(binding);
|
|
3121
|
+
} else if (!this.tracksBinding(binding)) {
|
|
3122
|
+
this.staticBindingsByDependency[dependency].push(binding);
|
|
3123
|
+
}
|
|
3124
|
+
}
|
|
3125
|
+
}
|
|
3126
|
+
}
|
|
3127
|
+
updateTrackedDependencies(binding, nextDependencies) {
|
|
3128
|
+
const previousDependencies = this.trackedDependenciesByBinding.get(binding);
|
|
3129
|
+
if (previousDependencies) {
|
|
3130
|
+
for (const dependency of previousDependencies) {
|
|
3131
|
+
if (!nextDependencies.has(dependency)) {
|
|
3132
|
+
this.trackedBindingsByDependency[dependency]?.delete(binding);
|
|
3133
|
+
}
|
|
3134
|
+
}
|
|
3135
|
+
}
|
|
3136
|
+
for (const dependency of nextDependencies) {
|
|
3137
|
+
if (!previousDependencies?.has(dependency)) {
|
|
3138
|
+
this.trackedBindingsByDependency[dependency]?.add(binding);
|
|
3139
|
+
}
|
|
3140
|
+
}
|
|
3141
|
+
this.trackedDependenciesByBinding.set(binding, nextDependencies);
|
|
3142
|
+
}
|
|
3143
|
+
readBinding(binding) {
|
|
3144
|
+
if (!this.tracksBinding(binding)) return binding.read(this.props, this.cells);
|
|
3145
|
+
const previousBinding = this.activeBinding;
|
|
3146
|
+
const previousDependencies = this.activeDependencies;
|
|
3147
|
+
const nextDependencies = /* @__PURE__ */ new Set();
|
|
3148
|
+
this.activeBinding = binding;
|
|
3149
|
+
this.activeDependencies = nextDependencies;
|
|
3150
|
+
try {
|
|
3151
|
+
return binding.read(this.props, this.cells);
|
|
3152
|
+
} finally {
|
|
3153
|
+
this.activeBinding = previousBinding;
|
|
3154
|
+
this.activeDependencies = previousDependencies;
|
|
3155
|
+
this.updateTrackedDependencies(binding, nextDependencies);
|
|
3156
|
+
}
|
|
3157
|
+
}
|
|
3158
|
+
bindingValue(binding, value) {
|
|
3159
|
+
return binding.kind === "text" ? renderTextValue(value) : value;
|
|
3160
|
+
}
|
|
3161
|
+
primeHybridBindings() {
|
|
3162
|
+
if (!this.usesHybridReactivity()) return;
|
|
3163
|
+
for (const binding of definitionReference.current.bindings) {
|
|
3164
|
+
if (binding.kind === "block") continue;
|
|
3165
|
+
if (!this.tracksBinding(binding)) continue;
|
|
3166
|
+
const value = this.readBinding(binding);
|
|
3167
|
+
this.bindingValues.set(binding, this.bindingValue(binding, value));
|
|
3168
|
+
}
|
|
1398
3169
|
}
|
|
1399
3170
|
bindingTarget(id) {
|
|
1400
3171
|
const existing = this.bindingTargetRefs.get(id);
|
|
@@ -1452,83 +3223,118 @@ function createCompiledComponent(definition) {
|
|
|
1452
3223
|
this.flushQueued = true;
|
|
1453
3224
|
queueMicrotask(() => {
|
|
1454
3225
|
this.flushQueued = false;
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
3226
|
+
this.flushBindingUpdates();
|
|
3227
|
+
});
|
|
3228
|
+
}
|
|
3229
|
+
flushBindingUpdates() {
|
|
3230
|
+
const inputSelection = this.inputSelection;
|
|
3231
|
+
this.inputSelection = null;
|
|
3232
|
+
if (!this.mounted) return;
|
|
3233
|
+
const dirty = /* @__PURE__ */ new Set();
|
|
3234
|
+
for (const index of this.dirtyState) {
|
|
3235
|
+
if (this.cells[index]?.flush()) dirty.add(index);
|
|
3236
|
+
}
|
|
3237
|
+
this.dirtyState.clear();
|
|
3238
|
+
if (dirty.size === 0) return;
|
|
3239
|
+
try {
|
|
3240
|
+
this.ensureBindingIndex();
|
|
3241
|
+
const affectedBlockIds = /* @__PURE__ */ new Set();
|
|
3242
|
+
const affectedBindings = /* @__PURE__ */ new Set();
|
|
3243
|
+
for (const dependency of dirty) {
|
|
3244
|
+
for (const binding of this.blockBindingsByDependency[dependency] || []) {
|
|
3245
|
+
affectedBlockIds.add(binding.id);
|
|
1474
3246
|
}
|
|
1475
|
-
const
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
parent = blockBindings.get(parent)?.parent;
|
|
1482
|
-
}
|
|
1483
|
-
return false;
|
|
1484
|
-
};
|
|
1485
|
-
const blockRefreshes = [...affectedBlockIds].map((id) => {
|
|
1486
|
-
const binding = blockBindings.get(id);
|
|
1487
|
-
const refresh = this.blockRefreshListeners.get(id);
|
|
1488
|
-
return binding && refresh && !hasAffectedMountedAncestor(binding) ? refresh : void 0;
|
|
1489
|
-
}).filter(
|
|
1490
|
-
(refresh) => refresh !== void 0
|
|
1491
|
-
);
|
|
1492
|
-
for (const binding of bindings) {
|
|
1493
|
-
if (binding.kind !== "block" && binding.dependencies.some((dependency) => dirty.has(dependency))) {
|
|
1494
|
-
this.applyBinding(binding);
|
|
3247
|
+
for (const binding of this.staticBindingsByDependency[dependency] || []) {
|
|
3248
|
+
affectedBindings.add(binding);
|
|
3249
|
+
}
|
|
3250
|
+
if (this.usesHybridReactivity()) {
|
|
3251
|
+
for (const binding of this.trackedBindingsByDependency[dependency] || []) {
|
|
3252
|
+
affectedBindings.add(binding);
|
|
1495
3253
|
}
|
|
1496
3254
|
}
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
3255
|
+
}
|
|
3256
|
+
const hasAffectedMountedAncestor = (binding) => {
|
|
3257
|
+
let parent = binding.parent;
|
|
3258
|
+
while (parent !== void 0) {
|
|
3259
|
+
if (affectedBlockIds.has(parent) && this.blockRefreshListeners.has(parent)) {
|
|
3260
|
+
return true;
|
|
3261
|
+
}
|
|
3262
|
+
parent = this.blockBindings.get(parent)?.parent;
|
|
1503
3263
|
}
|
|
1504
|
-
|
|
1505
|
-
}
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
this.
|
|
3264
|
+
return false;
|
|
3265
|
+
};
|
|
3266
|
+
const blockRefreshes = [...affectedBlockIds].map((id) => {
|
|
3267
|
+
const binding = this.blockBindings.get(id);
|
|
3268
|
+
const refresh = this.blockRefreshListeners.get(id);
|
|
3269
|
+
return binding && refresh && !hasAffectedMountedAncestor(binding) ? refresh : void 0;
|
|
3270
|
+
}).filter((refresh) => refresh !== void 0);
|
|
3271
|
+
for (const binding of affectedBindings) {
|
|
3272
|
+
if (binding.kind !== "block") this.applyBinding(binding);
|
|
1509
3273
|
}
|
|
1510
|
-
|
|
3274
|
+
let pendingBlockCommits = blockRefreshes.length;
|
|
3275
|
+
for (const refresh of blockRefreshes) {
|
|
3276
|
+
refresh(() => {
|
|
3277
|
+
pendingBlockCommits -= 1;
|
|
3278
|
+
if (pendingBlockCommits === 0) this.restoreInputSelection(inputSelection);
|
|
3279
|
+
}, dirty);
|
|
3280
|
+
}
|
|
3281
|
+
if (blockRefreshes.length === 0) this.restoreInputSelection(inputSelection);
|
|
3282
|
+
} catch (error) {
|
|
3283
|
+
this.bindingError = error;
|
|
3284
|
+
this.hasBindingError = true;
|
|
3285
|
+
this.forceUpdate();
|
|
3286
|
+
}
|
|
1511
3287
|
}
|
|
1512
|
-
applyBinding(binding) {
|
|
3288
|
+
applyBinding(binding, force = false) {
|
|
1513
3289
|
if (!this.root || binding.kind === "block") return;
|
|
1514
3290
|
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;
|
|
1515
3291
|
if (!target) return;
|
|
1516
|
-
const value =
|
|
3292
|
+
const value = this.readBinding(binding);
|
|
3293
|
+
const comparableValue = this.bindingValue(binding, value);
|
|
3294
|
+
if (!force && this.bindingValues.has(binding)) {
|
|
3295
|
+
if (Object.is(this.bindingValues.get(binding), comparableValue)) return;
|
|
3296
|
+
}
|
|
1517
3297
|
if (binding.kind === "text") {
|
|
1518
|
-
target.textContent =
|
|
3298
|
+
target.textContent = comparableValue;
|
|
1519
3299
|
} else if (binding.kind === "style") {
|
|
1520
3300
|
updateStyle(target, binding.name, value);
|
|
1521
3301
|
} else {
|
|
1522
3302
|
updateAttribute(target, binding.name, value);
|
|
1523
3303
|
}
|
|
3304
|
+
this.bindingValues.set(binding, comparableValue);
|
|
1524
3305
|
}
|
|
1525
3306
|
componentDidMount() {
|
|
1526
3307
|
this.mounted = true;
|
|
1527
3308
|
refreshListeners.add(this.refreshDefinition);
|
|
3309
|
+
this.ensureBindingIndex();
|
|
3310
|
+
this.primeHybridBindings();
|
|
1528
3311
|
}
|
|
1529
|
-
|
|
3312
|
+
getSnapshotBeforeUpdate() {
|
|
3313
|
+
const currentDefinition = definitionReference.current;
|
|
3314
|
+
const propValues = currentDefinition.readProps?.(this.props) || null;
|
|
3315
|
+
return this.canReuseRenderedElement(currentDefinition, propValues);
|
|
3316
|
+
}
|
|
3317
|
+
componentDidUpdate(_previousProps, _previousState, reusedRenderedElement = false) {
|
|
3318
|
+
const propValues = definitionReference.current.readProps?.(this.props) || null;
|
|
3319
|
+
if (propValues) {
|
|
3320
|
+
if (reusedRenderedElement) this.captureInputSelection();
|
|
3321
|
+
for (let propIndex = 0; propIndex < propValues.length; propIndex += 1) {
|
|
3322
|
+
const cellIndex = this.propCellOffset + propIndex;
|
|
3323
|
+
const cell = this.cells[cellIndex];
|
|
3324
|
+
if (!cell) continue;
|
|
3325
|
+
cell.replace(propValues[propIndex]);
|
|
3326
|
+
if (reusedRenderedElement) {
|
|
3327
|
+
this.dirtyState.add(cellIndex);
|
|
3328
|
+
} else {
|
|
3329
|
+
cell.flush();
|
|
3330
|
+
}
|
|
3331
|
+
}
|
|
3332
|
+
this.flushBindingUpdates();
|
|
3333
|
+
return;
|
|
3334
|
+
}
|
|
3335
|
+
this.ensureBindingIndex();
|
|
1530
3336
|
for (const binding of definitionReference.current.bindings) {
|
|
1531
|
-
if (binding.kind !== "block") this.applyBinding(binding);
|
|
3337
|
+
if (binding.kind !== "block") this.applyBinding(binding, true);
|
|
1532
3338
|
}
|
|
1533
3339
|
}
|
|
1534
3340
|
componentWillUnmount() {
|
|
@@ -1541,36 +3347,68 @@ function createCompiledComponent(definition) {
|
|
|
1541
3347
|
this.blockRootElements.clear();
|
|
1542
3348
|
this.bindingTargets.clear();
|
|
1543
3349
|
this.bindingTargetRefs.clear();
|
|
3350
|
+
this.indexedDefinition = null;
|
|
3351
|
+
this.staticBindingsByDependency = [];
|
|
3352
|
+
this.blockBindingsByDependency = [];
|
|
3353
|
+
this.blockBindings.clear();
|
|
3354
|
+
this.trackedBindingsByDependency = [];
|
|
3355
|
+
this.trackedDependenciesByBinding.clear();
|
|
3356
|
+
this.bindingValues.clear();
|
|
3357
|
+
this.activeBinding = null;
|
|
3358
|
+
this.activeDependencies = null;
|
|
1544
3359
|
refreshListeners.delete(this.refreshDefinition);
|
|
1545
3360
|
}
|
|
1546
3361
|
render() {
|
|
1547
3362
|
if (this.hasBindingError) throw this.bindingError;
|
|
1548
3363
|
const currentDefinition = definitionReference.current;
|
|
1549
|
-
const
|
|
3364
|
+
const propValues = currentDefinition.readProps?.(this.props) || null;
|
|
3365
|
+
if (this.canReuseRenderedElement(currentDefinition, propValues)) {
|
|
3366
|
+
return this.renderedElement;
|
|
3367
|
+
}
|
|
3368
|
+
const renderCells = this.renderCellsForProps(propValues);
|
|
3369
|
+
const element = currentDefinition.render(this.props, renderCells.cells, this.blockRuntime);
|
|
1550
3370
|
if (!React.isValidElement(element)) {
|
|
1551
3371
|
throw new TypeError(
|
|
1552
3372
|
`Compiled component ${currentDefinition.displayName} must return one host element.`
|
|
1553
3373
|
);
|
|
1554
3374
|
}
|
|
3375
|
+
let renderedElement;
|
|
3376
|
+
const captureCommittedRoot = (root) => {
|
|
3377
|
+
this.captureRoot(root);
|
|
3378
|
+
if (!root) return;
|
|
3379
|
+
renderCells.commit();
|
|
3380
|
+
this.renderedDefinition = currentDefinition;
|
|
3381
|
+
this.renderedElement = renderedElement;
|
|
3382
|
+
};
|
|
1555
3383
|
if (element.type === this.blockRuntime.KeyedRanges) {
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
3384
|
+
renderedElement = React.cloneElement(
|
|
3385
|
+
element,
|
|
3386
|
+
{
|
|
3387
|
+
rootRef: captureCommittedRoot
|
|
3388
|
+
}
|
|
3389
|
+
);
|
|
3390
|
+
} else if (element.type === this.blockRuntime.ConditionalRanges) {
|
|
3391
|
+
renderedElement = React.cloneElement(
|
|
1562
3392
|
element,
|
|
1563
|
-
{ rootRef:
|
|
3393
|
+
{ rootRef: captureCommittedRoot }
|
|
1564
3394
|
);
|
|
1565
|
-
}
|
|
1566
|
-
|
|
3395
|
+
} else if (element.type === this.blockRuntime.MixedRanges) {
|
|
3396
|
+
renderedElement = React.cloneElement(
|
|
3397
|
+
element,
|
|
3398
|
+
{
|
|
3399
|
+
rootRef: captureCommittedRoot
|
|
3400
|
+
}
|
|
3401
|
+
);
|
|
3402
|
+
} else if (typeof element.type !== "string") {
|
|
1567
3403
|
throw new TypeError(
|
|
1568
3404
|
`Compiled component ${currentDefinition.displayName} must return one host element.`
|
|
1569
3405
|
);
|
|
3406
|
+
} else {
|
|
3407
|
+
renderedElement = React.cloneElement(element, {
|
|
3408
|
+
ref: captureCommittedRoot
|
|
3409
|
+
});
|
|
1570
3410
|
}
|
|
1571
|
-
return
|
|
1572
|
-
ref: this.captureRoot
|
|
1573
|
-
});
|
|
3411
|
+
return renderedElement;
|
|
1574
3412
|
}
|
|
1575
3413
|
}
|
|
1576
3414
|
FarmCompiledComponent.displayName = `FarmCompiled(${definition.displayName})`;
|
|
@@ -1580,12 +3418,26 @@ function createCompiledComponent(definition) {
|
|
|
1580
3418
|
component,
|
|
1581
3419
|
definition: definitionReference,
|
|
1582
3420
|
refreshListeners,
|
|
1583
|
-
stateSignature
|
|
3421
|
+
stateSignature,
|
|
3422
|
+
runtimeSignature
|
|
1584
3423
|
});
|
|
1585
3424
|
}
|
|
1586
3425
|
return component;
|
|
1587
3426
|
}
|
|
3427
|
+
var COMPLETE_RUNTIME_FEATURES = [
|
|
3428
|
+
conditionalRuntimeFeature,
|
|
3429
|
+
hostConditionalRuntimeFeature,
|
|
3430
|
+
conditionalRangesRuntimeFeature,
|
|
3431
|
+
keyedListRuntimeFeature,
|
|
3432
|
+
keyedRowsCompleteRuntimeFeature,
|
|
3433
|
+
keyedRangesRuntimeFeature,
|
|
3434
|
+
mixedRangesRuntimeFeature,
|
|
3435
|
+
componentRuntimeFeature
|
|
3436
|
+
];
|
|
3437
|
+
function createCompiledComponent(definition) {
|
|
3438
|
+
return createCompiledComponentWithFeatures(definition, COMPLETE_RUNTIME_FEATURES);
|
|
3439
|
+
}
|
|
1588
3440
|
|
|
1589
|
-
export { createCompiledComponent };
|
|
3441
|
+
export { componentRuntimeFeature, conditionalRangesRuntimeFeature, conditionalRuntimeFeature, createCompiledComponent, createCompiledComponentWithFeatures, hostConditionalRuntimeFeature, keyedListRuntimeFeature, keyedRangesRuntimeFeature, keyedRowsCompleteRuntimeFeature, keyedRowsConditionalRuntimeFeature, keyedRowsHostRuntimeFeature, keyedRowsRuntimeFeature, mixedRangesRuntimeFeature };
|
|
1590
3442
|
//# sourceMappingURL=compiler-runtime.mjs.map
|
|
1591
3443
|
//# sourceMappingURL=compiler-runtime.mjs.map
|