@farm.js/react 0.1.0-beta.12 → 0.1.0-beta.13

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.
@@ -335,8 +335,10 @@ interface CompiledComponentDefinition<Props> {
335
335
  }
336
336
  type CompilerBlockRefresh = (afterCommit?: () => void, dirtyState?: ReadonlySet<number>) => void;
337
337
  interface CompilerRuntimeFeatureOwner {
338
- setRoot(id: number, root: Element | null): void;
338
+ setRoot(id: number, root: Element | null, expectedRoot?: Element | null): void;
339
339
  subscribe(id: number, refresh: CompilerBlockRefresh): () => void;
340
+ /** Opaque identity used to detect compatible definition replacement. */
341
+ getDefinitionVersion?(): unknown;
340
342
  }
341
343
  interface CompilerRuntimeFeature {
342
344
  /** Stable identity used by Fast Refresh compatibility checks. */
@@ -335,8 +335,10 @@ interface CompiledComponentDefinition<Props> {
335
335
  }
336
336
  type CompilerBlockRefresh = (afterCommit?: () => void, dirtyState?: ReadonlySet<number>) => void;
337
337
  interface CompilerRuntimeFeatureOwner {
338
- setRoot(id: number, root: Element | null): void;
338
+ setRoot(id: number, root: Element | null, expectedRoot?: Element | null): void;
339
339
  subscribe(id: number, refresh: CompilerBlockRefresh): () => void;
340
+ /** Opaque identity used to detect compatible definition replacement. */
341
+ getDefinitionVersion?(): unknown;
340
342
  }
341
343
  interface CompilerRuntimeFeature {
342
344
  /** Stable identity used by Fast Refresh compatibility checks. */
@@ -1742,8 +1742,18 @@ function createConditionalBlockComponent(owner) {
1742
1742
  class FarmConditionalBlock extends React.Component {
1743
1743
  constructor() {
1744
1744
  super(...arguments);
1745
+ this.root = null;
1745
1746
  this.captureRoot = (root) => {
1747
+ const previousRoot = this.root;
1748
+ const previousId = this.rootId;
1749
+ this.root = root;
1750
+ if (!root) {
1751
+ if (previousId !== void 0) owner.setRoot(previousId, null, previousRoot);
1752
+ this.rootId = void 0;
1753
+ return;
1754
+ }
1746
1755
  owner.setRoot(this.props.id, root);
1756
+ this.rootId = this.props.id;
1747
1757
  };
1748
1758
  this.refresh = (afterCommit) => {
1749
1759
  this.forceUpdate(afterCommit);
@@ -1758,7 +1768,11 @@ function createConditionalBlockComponent(owner) {
1758
1768
  componentDidUpdate(previous) {
1759
1769
  if (previous.id === this.props.id) return;
1760
1770
  this.unsubscribe?.();
1761
- owner.setRoot(previous.id, null);
1771
+ if (this.root && this.rootId !== this.props.id) {
1772
+ if (this.rootId !== void 0) owner.setRoot(this.rootId, null, this.root);
1773
+ owner.setRoot(this.props.id, this.root);
1774
+ this.rootId = this.props.id;
1775
+ }
1762
1776
  this.subscribe();
1763
1777
  }
1764
1778
  componentWillUnmount() {
@@ -3251,6 +3265,7 @@ function createHostConditionalBlockComponent(owner) {
3251
3265
  this.fallbackKeysWereUnsafe = false;
3252
3266
  this.activeBranch = null;
3253
3267
  this.instance = null;
3268
+ this.definitionVersion = owner.getDefinitionVersion?.();
3254
3269
  this.requestNestedFallback = () => {
3255
3270
  this.instance?.scope?.cleanup();
3256
3271
  this.activateFallback();
@@ -3299,6 +3314,7 @@ function createHostConditionalBlockComponent(owner) {
3299
3314
  if (selection.kind === "fallback") return false;
3300
3315
  if (selection.kind === "empty") {
3301
3316
  if (this.root.childNodes.length !== 0) return false;
3317
+ this.instance?.scope?.cleanup();
3302
3318
  this.activeBranch = null;
3303
3319
  this.instance = null;
3304
3320
  return true;
@@ -3317,6 +3333,7 @@ function createHostConditionalBlockComponent(owner) {
3317
3333
  this.requestNestedFallback
3318
3334
  );
3319
3335
  if (!instance) return false;
3336
+ this.instance?.scope?.cleanup();
3320
3337
  this.activeBranch = selection.key;
3321
3338
  this.instance = instance;
3322
3339
  return true;
@@ -3395,35 +3412,58 @@ function createHostConditionalBlockComponent(owner) {
3395
3412
  this.instance = instance;
3396
3413
  afterCommit?.();
3397
3414
  }
3415
+ listen() {
3416
+ const id = this.currentProps.id;
3417
+ const stop = this.stop;
3418
+ if (this.id === id) return;
3419
+ stop?.();
3420
+ this.stop = owner.subscribe(id, this.refresh);
3421
+ this.id = id;
3422
+ }
3398
3423
  schedulePropSync() {
3399
3424
  if (this.propSyncQueued) return;
3400
3425
  this.propSyncQueued = true;
3401
3426
  queueMicrotask(() => {
3402
3427
  this.propSyncQueued = false;
3403
- if (this.mounted && !this.state.fallback) this.reconcile();
3428
+ if (this.mounted && !this.state.fallback) {
3429
+ this.listen();
3430
+ this.reconcile();
3431
+ }
3404
3432
  });
3405
3433
  }
3406
3434
  shouldComponentUpdate(nextProps, nextState) {
3435
+ const definitionChanged = this.definitionVersion !== owner.getDefinitionVersion?.();
3407
3436
  this.currentProps = nextProps;
3408
3437
  if (this.state.fallback && nextState.fallback) this.prepareFallbackUpdate();
3409
3438
  if (nextState.fallback || this.state.fallback) return true;
3439
+ if (definitionChanged) return true;
3410
3440
  this.schedulePropSync();
3411
3441
  return false;
3412
3442
  }
3413
3443
  componentDidMount() {
3414
3444
  this.mounted = true;
3415
- this.unsubscribe = owner.subscribe(this.props.id, this.refresh);
3445
+ this.listen();
3416
3446
  if (this.state.fallback || this.fallbackRequested) {
3417
3447
  this.subscribeFallbackDescendants();
3418
3448
  this.fallbackKeysWereUnsafe = this.hasUnsafeFallbackKeys();
3419
3449
  } else if (!this.adopt()) this.activateFallback();
3420
3450
  }
3421
3451
  componentDidUpdate() {
3422
- if (this.state.fallback) this.subscribeFallbackDescendants();
3452
+ this.listen();
3453
+ const nextDefinitionVersion = owner.getDefinitionVersion?.();
3454
+ const definitionChanged = this.definitionVersion !== nextDefinitionVersion;
3455
+ this.definitionVersion = nextDefinitionVersion;
3456
+ if (this.state.fallback) {
3457
+ this.subscribeFallbackDescendants();
3458
+ } else if (definitionChanged && !this.adopt()) {
3459
+ this.activateFallback();
3460
+ }
3423
3461
  }
3424
3462
  componentWillUnmount() {
3425
3463
  this.mounted = false;
3426
- this.unsubscribe?.();
3464
+ const stop = this.stop;
3465
+ stop?.();
3466
+ this.id = void 0;
3427
3467
  clearCompilerFallbackSubscriptions(this.fallbackUnsubscribers);
3428
3468
  this.fallbackKeysWereUnsafe = false;
3429
3469
  this.instance?.scope?.cleanup();
@@ -3462,6 +3502,7 @@ function createConditionalRangesBlockComponent(owner) {
3462
3502
  this.rangeInstances = [];
3463
3503
  this.staticSegments = [];
3464
3504
  this.staticValues = [];
3505
+ this.definitionVersion = owner.getDefinitionVersion?.();
3465
3506
  this.requestNestedFallback = () => {
3466
3507
  for (const instance of this.rangeInstances) instance?.host.scope?.cleanup();
3467
3508
  this.activateFallback();
@@ -3528,6 +3569,7 @@ function createConditionalRangesBlockComponent(owner) {
3528
3569
  const elements = [...this.root.children];
3529
3570
  const staticSegments = [];
3530
3571
  const instances = [];
3572
+ const staticValues = this.staticValues.slice();
3531
3573
  const cleanupInstances = () => {
3532
3574
  for (const instance of instances) instance?.host.scope?.cleanup();
3533
3575
  };
@@ -3582,14 +3624,15 @@ function createConditionalRangesBlockComponent(owner) {
3582
3624
  return false;
3583
3625
  }
3584
3626
  staticSegments.push(elements.slice(cursor));
3585
- this.staticSegments = staticSegments;
3586
- this.rangeInstances = instances;
3587
- if (!applyStaticRangeBindings(props.bindings, this.staticSegments, this.staticValues)) {
3627
+ if (!applyStaticRangeBindings(props.bindings, staticSegments, staticValues)) {
3588
3628
  cleanupInstances();
3589
- this.rangeInstances = [];
3590
- this.staticSegments = [];
3591
3629
  return false;
3592
3630
  }
3631
+ for (const instance of this.rangeInstances) instance?.host.scope?.cleanup();
3632
+ this.staticSegments = staticSegments;
3633
+ this.rangeInstances = instances;
3634
+ this.staticValues.length = 0;
3635
+ this.staticValues.push(...staticValues);
3593
3636
  return true;
3594
3637
  }
3595
3638
  anchorAfter(rangeIndex) {
@@ -3684,6 +3727,14 @@ function createConditionalRangesBlockComponent(owner) {
3684
3727
  }
3685
3728
  afterCommit?.();
3686
3729
  }
3730
+ listen() {
3731
+ const id = this.currentProps.id;
3732
+ const stop = this.stop;
3733
+ if (this.id === id) return;
3734
+ stop?.();
3735
+ this.stop = owner.subscribe(id, this.refresh);
3736
+ this.id = id;
3737
+ }
3687
3738
  activateFallback(afterCommit) {
3688
3739
  if (!this.mounted || this.state.fallback || this.fallbackRequested) {
3689
3740
  afterCommit?.();
@@ -3700,30 +3751,45 @@ function createConditionalRangesBlockComponent(owner) {
3700
3751
  this.propFallbackQueued = true;
3701
3752
  queueMicrotask(() => {
3702
3753
  this.propFallbackQueued = false;
3703
- if (this.mounted && !this.state.fallback) this.activateFallback();
3754
+ if (this.mounted && !this.state.fallback) {
3755
+ this.listen();
3756
+ this.activateFallback();
3757
+ }
3704
3758
  });
3705
3759
  }
3706
3760
  shouldComponentUpdate(nextProps, nextState) {
3761
+ const definitionChanged = this.definitionVersion !== owner.getDefinitionVersion?.();
3707
3762
  this.currentProps = nextProps;
3708
3763
  if (this.state.fallback && nextState.fallback) this.prepareFallbackUpdate();
3709
3764
  if (nextState.fallback || this.state.fallback) return true;
3765
+ if (definitionChanged) return true;
3710
3766
  this.schedulePropFallback();
3711
3767
  return false;
3712
3768
  }
3713
3769
  componentDidMount() {
3714
3770
  this.mounted = true;
3715
- this.unsubscribe = owner.subscribe(this.props.id, this.refresh);
3771
+ this.listen();
3716
3772
  if (this.state.fallback || this.fallbackRequested) {
3717
3773
  this.subscribeFallbackDescendants();
3718
3774
  this.fallbackKeysWereUnsafe = this.hasUnsafeFallbackKeys();
3719
3775
  } else if (!this.adopt()) this.activateFallback();
3720
3776
  }
3721
3777
  componentDidUpdate() {
3722
- if (this.state.fallback) this.subscribeFallbackDescendants();
3778
+ this.listen();
3779
+ const nextDefinitionVersion = owner.getDefinitionVersion?.();
3780
+ const definitionChanged = this.definitionVersion !== nextDefinitionVersion;
3781
+ this.definitionVersion = nextDefinitionVersion;
3782
+ if (this.state.fallback) {
3783
+ this.subscribeFallbackDescendants();
3784
+ } else if (definitionChanged && !this.adopt()) {
3785
+ this.activateFallback();
3786
+ }
3723
3787
  }
3724
3788
  componentWillUnmount() {
3725
3789
  this.mounted = false;
3726
- this.unsubscribe?.();
3790
+ const stop = this.stop;
3791
+ stop?.();
3792
+ this.id = void 0;
3727
3793
  clearCompilerFallbackSubscriptions(this.fallbackUnsubscribers);
3728
3794
  this.fallbackKeysWereUnsafe = false;
3729
3795
  for (const instance of this.rangeInstances) instance?.host.scope?.cleanup();
@@ -5512,6 +5578,7 @@ function createKeyedRowsBlockComponent(owner, options = {}) {
5512
5578
  this.fallbackKeysWereUnsafe = false;
5513
5579
  this.propSyncQueued = false;
5514
5580
  this.currentProps = this.props;
5581
+ this.definitionVersion = owner.getDefinitionVersion?.();
5515
5582
  this.instances = /* @__PURE__ */ new Map();
5516
5583
  this.identityTargets = /* @__PURE__ */ new Map();
5517
5584
  this.membershipTargets = /* @__PURE__ */ new Map();
@@ -5890,13 +5957,14 @@ function createKeyedRowsBlockComponent(owner, options = {}) {
5890
5957
  const rows = this.readRows(this.currentProps);
5891
5958
  const elements = [...this.root.children];
5892
5959
  if (!rows || rows.items.length !== elements.length) return false;
5960
+ const reactOwnedRows = this.hasReactOwnedRows();
5893
5961
  const opaqueConditionalPaths = new Set(
5894
5962
  (this.currentProps.conditionals || []).map((conditional) => conditional.path.join("."))
5895
5963
  );
5896
5964
  const instances = /* @__PURE__ */ new Map();
5897
5965
  for (let index = 0; index < rows.items.length; index += 1) {
5898
5966
  const descriptor = this.currentProps.create(rows.items[index], index);
5899
- if (this.hasReactOwnedRows() && !matchesCompilerHostElement(elements[index], descriptor, opaqueConditionalPaths)) {
5967
+ if (reactOwnedRows && !matchesCompilerHostElement(elements[index], descriptor, opaqueConditionalPaths)) {
5900
5968
  this.cleanupHostScopes(instances);
5901
5969
  return false;
5902
5970
  }
@@ -5909,7 +5977,7 @@ function createKeyedRowsBlockComponent(owner, options = {}) {
5909
5977
  key: rows.keys[index],
5910
5978
  element: elements[index],
5911
5979
  scope: scope || void 0,
5912
- values: this.hasReactOwnedRows() ? this.currentProps.bindings.map(() => UNSET_KEYED_ROW_BINDING) : readKeyedRowBindingValues(this.currentProps, rows.items[index], index),
5980
+ values: reactOwnedRows ? this.currentProps.bindings.map(() => UNSET_KEYED_ROW_BINDING) : readKeyedRowBindingValues(this.currentProps, rows.items[index], index),
5913
5981
  item: rows.items[index],
5914
5982
  index,
5915
5983
  conditionalValues: this.readConditionalValues(
@@ -5918,11 +5986,13 @@ function createKeyedRowsBlockComponent(owner, options = {}) {
5918
5986
  index
5919
5987
  )
5920
5988
  };
5921
- if (this.hasReactOwnedRows()) {
5922
- applyKeyedRowBindings(this.currentProps, instance, rows.items[index], index);
5923
- }
5924
5989
  instances.set(rows.keys[index], instance);
5925
5990
  }
5991
+ if (reactOwnedRows) {
5992
+ for (const instance of instances.values()) {
5993
+ applyKeyedRowBindings(this.currentProps, instance, instance.item, instance.index);
5994
+ }
5995
+ }
5926
5996
  this.cleanupHostScopes();
5927
5997
  this.instances = instances;
5928
5998
  this.rebuildElementIndex(instances);
@@ -6344,17 +6414,29 @@ function createKeyedRowsBlockComponent(owner, options = {}) {
6344
6414
  this.commitCurrentCollection(dirtyState);
6345
6415
  this.notifyConditionalChanges(conditionalChanges, afterCommit);
6346
6416
  }
6417
+ listen() {
6418
+ const id = this.currentProps.id;
6419
+ const stop = this.stop;
6420
+ if (this.id === id) return;
6421
+ stop?.();
6422
+ this.stop = owner.subscribe(id, this.refresh);
6423
+ this.id = id;
6424
+ }
6347
6425
  schedulePropSync() {
6348
6426
  if (this.propSyncQueued) return;
6349
6427
  this.propSyncQueued = true;
6350
6428
  queueMicrotask(() => {
6351
6429
  this.propSyncQueued = false;
6352
- if (this.mounted && !this.state.fallback) this.reconcile();
6430
+ if (this.mounted && !this.state.fallback) {
6431
+ this.listen();
6432
+ this.reconcile();
6433
+ }
6353
6434
  });
6354
6435
  }
6355
6436
  shouldComponentUpdate(nextProps, nextState) {
6356
6437
  const wasReactOwned = this.hasReactOwnedRows(this.currentProps);
6357
6438
  const willBeReactOwned = this.hasReactOwnedRows(nextProps);
6439
+ const definitionChanged = this.definitionVersion !== owner.getDefinitionVersion?.();
6358
6440
  this.currentProps = nextProps;
6359
6441
  if (this.state.fallback && nextState.fallback) {
6360
6442
  const unsafeKeys = this.hasUnsafeFallbackKeys();
@@ -6362,7 +6444,7 @@ function createKeyedRowsBlockComponent(owner, options = {}) {
6362
6444
  this.fallbackKeysWereUnsafe = unsafeKeys;
6363
6445
  }
6364
6446
  if (nextState.fallback || this.state.fallback) return true;
6365
- if (wasReactOwned || willBeReactOwned) {
6447
+ if (definitionChanged || wasReactOwned || willBeReactOwned) {
6366
6448
  this.eventHandlers.clear();
6367
6449
  return true;
6368
6450
  }
@@ -6370,19 +6452,25 @@ function createKeyedRowsBlockComponent(owner, options = {}) {
6370
6452
  return false;
6371
6453
  }
6372
6454
  componentDidUpdate(previousProps) {
6373
- if (this.state.fallback || previousProps === this.props || !this.hasReactOwnedRows(previousProps) && !this.hasReactOwnedRows(this.props) || this.adopt()) {
6455
+ this.listen();
6456
+ const nextDefinitionVersion = owner.getDefinitionVersion?.();
6457
+ const definitionChanged = this.definitionVersion !== nextDefinitionVersion;
6458
+ this.definitionVersion = nextDefinitionVersion;
6459
+ if (this.state.fallback || previousProps === this.props || !definitionChanged && !this.hasReactOwnedRows(previousProps) && !this.hasReactOwnedRows(this.props) || this.adopt()) {
6374
6460
  return;
6375
6461
  }
6376
6462
  this.activateFallback();
6377
6463
  }
6378
6464
  componentDidMount() {
6379
6465
  this.mounted = true;
6380
- this.unsubscribe = owner.subscribe(this.props.id, this.refresh);
6466
+ this.listen();
6381
6467
  if (!this.adopt()) this.activateFallback();
6382
6468
  }
6383
6469
  componentWillUnmount() {
6384
6470
  this.mounted = false;
6385
- this.unsubscribe?.();
6471
+ const stop = this.stop;
6472
+ stop?.();
6473
+ this.id = void 0;
6386
6474
  this.cleanupHostScopes();
6387
6475
  this.instances.clear();
6388
6476
  this.identityTargets.clear();
@@ -6425,6 +6513,7 @@ function createKeyedRangesBlockComponent(owner) {
6425
6513
  this.rangeInstances = [];
6426
6514
  this.staticSegments = [];
6427
6515
  this.staticValues = [];
6516
+ this.definitionVersion = owner.getDefinitionVersion?.();
6428
6517
  this.captureRoot = (root) => {
6429
6518
  this.root = root;
6430
6519
  this.currentProps.rootRef?.(root);
@@ -6462,6 +6551,7 @@ function createKeyedRangesBlockComponent(owner) {
6462
6551
  const elements = [...this.root.children];
6463
6552
  const staticSegments = [];
6464
6553
  const instancesByRange = [];
6554
+ const staticValues = this.staticValues.slice();
6465
6555
  let cursor = 0;
6466
6556
  for (let rangeIndex = 0; rangeIndex < props.ranges.length; rangeIndex += 1) {
6467
6557
  const range = props.ranges[rangeIndex];
@@ -6493,13 +6583,11 @@ function createKeyedRangesBlockComponent(owner) {
6493
6583
  }
6494
6584
  if (cursor + props.trailing !== elements.length) return false;
6495
6585
  staticSegments.push(elements.slice(cursor));
6586
+ if (!applyStaticRangeBindings(props.bindings, staticSegments, staticValues)) return false;
6496
6587
  this.staticSegments = staticSegments;
6497
6588
  this.rangeInstances = instancesByRange;
6498
- if (!applyStaticRangeBindings(props.bindings, this.staticSegments, this.staticValues)) {
6499
- this.rangeInstances = [];
6500
- this.staticSegments = [];
6501
- return false;
6502
- }
6589
+ this.staticValues.length = 0;
6590
+ this.staticValues.push(...staticValues);
6503
6591
  return true;
6504
6592
  }
6505
6593
  anchorAfter(rangeIndex) {
@@ -6596,6 +6684,14 @@ function createKeyedRangesBlockComponent(owner) {
6596
6684
  }
6597
6685
  afterCommit?.();
6598
6686
  }
6687
+ listen() {
6688
+ const id = this.currentProps.id;
6689
+ const stop = this.stop;
6690
+ if (this.id === id) return;
6691
+ stop?.();
6692
+ this.stop = owner.subscribe(id, this.refresh);
6693
+ this.id = id;
6694
+ }
6599
6695
  activateFallback(afterCommit) {
6600
6696
  if (!this.mounted || this.state.fallback || this.fallbackRequested) {
6601
6697
  afterCommit?.();
@@ -6610,10 +6706,14 @@ function createKeyedRangesBlockComponent(owner) {
6610
6706
  this.propFallbackQueued = true;
6611
6707
  queueMicrotask(() => {
6612
6708
  this.propFallbackQueued = false;
6613
- if (this.mounted && !this.state.fallback) this.activateFallback();
6709
+ if (this.mounted && !this.state.fallback) {
6710
+ this.listen();
6711
+ this.activateFallback();
6712
+ }
6614
6713
  });
6615
6714
  }
6616
6715
  shouldComponentUpdate(nextProps, nextState) {
6716
+ const definitionChanged = this.definitionVersion !== owner.getDefinitionVersion?.();
6617
6717
  this.currentProps = nextProps;
6618
6718
  if (this.state.fallback && nextState.fallback) {
6619
6719
  const unsafeKeys = this.hasUnsafeFallbackKeys();
@@ -6621,17 +6721,27 @@ function createKeyedRangesBlockComponent(owner) {
6621
6721
  this.fallbackKeysWereUnsafe = unsafeKeys;
6622
6722
  }
6623
6723
  if (nextState.fallback || this.state.fallback) return true;
6724
+ if (definitionChanged) return true;
6624
6725
  this.schedulePropFallback();
6625
6726
  return false;
6626
6727
  }
6627
6728
  componentDidMount() {
6628
6729
  this.mounted = true;
6629
- this.unsubscribe = owner.subscribe(this.props.id, this.refresh);
6730
+ this.listen();
6630
6731
  if (!this.adopt()) this.activateFallback();
6631
6732
  }
6733
+ componentDidUpdate() {
6734
+ this.listen();
6735
+ const nextDefinitionVersion = owner.getDefinitionVersion?.();
6736
+ const definitionChanged = this.definitionVersion !== nextDefinitionVersion;
6737
+ this.definitionVersion = nextDefinitionVersion;
6738
+ if (!this.state.fallback && definitionChanged && !this.adopt()) this.activateFallback();
6739
+ }
6632
6740
  componentWillUnmount() {
6633
6741
  this.mounted = false;
6634
- this.unsubscribe?.();
6742
+ const stop = this.stop;
6743
+ stop?.();
6744
+ this.id = void 0;
6635
6745
  this.rangeInstances = [];
6636
6746
  this.staticSegments = [];
6637
6747
  this.staticValues.length = 0;
@@ -6666,6 +6776,7 @@ function createMixedRangesBlockComponent(owner) {
6666
6776
  this.currentProps = this.props;
6667
6777
  this.controller = null;
6668
6778
  this.fallbackUnsubscribers = /* @__PURE__ */ new Map();
6779
+ this.definitionVersion = owner.getDefinitionVersion?.();
6669
6780
  this.captureRoot = (root) => {
6670
6781
  this.root = root;
6671
6782
  this.currentProps.rootRef?.(root);
@@ -6739,7 +6850,9 @@ function createMixedRangesBlockComponent(owner) {
6739
6850
  controller.cleanup();
6740
6851
  throw error;
6741
6852
  }
6853
+ const previous = this.controller;
6742
6854
  this.controller = controller;
6855
+ previous?.cleanup();
6743
6856
  return true;
6744
6857
  }
6745
6858
  schedulePropFallback() {
@@ -6751,11 +6864,13 @@ function createMixedRangesBlockComponent(owner) {
6751
6864
  });
6752
6865
  }
6753
6866
  shouldComponentUpdate(nextProps, nextState) {
6867
+ const definitionChanged = this.definitionVersion !== owner.getDefinitionVersion?.();
6754
6868
  this.currentProps = nextProps;
6755
6869
  if (this.state.fallback && nextState.fallback) {
6756
6870
  this.prepareFallbackUpdate(this.currentProps.create());
6757
6871
  }
6758
6872
  if (nextState.fallback || this.state.fallback) return true;
6873
+ if (definitionChanged) return true;
6759
6874
  this.schedulePropFallback();
6760
6875
  return false;
6761
6876
  }
@@ -6767,7 +6882,14 @@ function createMixedRangesBlockComponent(owner) {
6767
6882
  } else if (!this.adopt()) this.activateFallback();
6768
6883
  }
6769
6884
  componentDidUpdate() {
6770
- if (this.state.fallback) this.subscribeFallbackBlocks();
6885
+ const nextDefinitionVersion = owner.getDefinitionVersion?.();
6886
+ const definitionChanged = this.definitionVersion !== nextDefinitionVersion;
6887
+ this.definitionVersion = nextDefinitionVersion;
6888
+ if (this.state.fallback) {
6889
+ this.subscribeFallbackBlocks();
6890
+ } else if (definitionChanged && !this.adopt()) {
6891
+ this.activateFallback();
6892
+ }
6771
6893
  }
6772
6894
  componentWillUnmount() {
6773
6895
  this.mounted = false;
@@ -7607,8 +7729,9 @@ function createCompiledComponentWithFeatures(definition, runtimeFeatures) {
7607
7729
  };
7608
7730
  });
7609
7731
  const featureOwner = {
7610
- setRoot: (id, root) => this.setBlockRoot(id, root),
7611
- subscribe: (id, refresh) => this.subscribeToBlock(id, refresh)
7732
+ setRoot: (id, root, expectedRoot) => this.setBlockRoot(id, root, expectedRoot),
7733
+ subscribe: (id, refresh) => this.subscribeToBlock(id, refresh),
7734
+ getDefinitionVersion: () => definitionReference.current
7612
7735
  };
7613
7736
  const blockRuntime = {
7614
7737
  target: (id) => this.bindingTarget(id)
@@ -7747,8 +7870,9 @@ function createCompiledComponentWithFeatures(definition, runtimeFeatures) {
7747
7870
  }
7748
7871
  snapshot.element.setSelectionRange(snapshot.start, snapshot.end, snapshot.direction);
7749
7872
  }
7750
- setBlockRoot(id, root) {
7873
+ setBlockRoot(id, root, expectedRoot) {
7751
7874
  const previous = this.blockRoots.get(id);
7875
+ if (!root && expectedRoot !== void 0 && previous !== expectedRoot) return;
7752
7876
  if (previous) this.blockRootElements.delete(previous);
7753
7877
  if (root) {
7754
7878
  this.blockRoots.set(id, root);