@viewfly/core 3.0.0-alpha.2 → 3.0.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.esm.js CHANGED
@@ -209,7 +209,7 @@ var NullInjector = class {
209
209
  * @param provider
210
210
  */
211
211
  function normalizeProvider(provider) {
212
- if (provider.useValue) return normalizeValueProviderFactory(provider);
212
+ if (Object.prototype.hasOwnProperty.call(provider, "useValue")) return normalizeValueProviderFactory(provider);
213
213
  if (provider.useClass) return normalizeClassProviderFactory(provider);
214
214
  if (provider.useExisting) return normalizeExistingProviderFactory(provider);
215
215
  if (provider.useFactory) return normalizeFactoryProviderFactory(provider);
@@ -345,13 +345,14 @@ var provideScopeError = (token) => {
345
345
  * 反射注入器
346
346
  */
347
347
  var ReflectiveInjector = class {
348
- normalizedProviders;
348
+ normalizedProviders = /* @__PURE__ */ new Map();
349
349
  recordValues = /* @__PURE__ */ new Map();
350
350
  constructor(parentInjector, staticProviders, scope) {
351
351
  this.parentInjector = parentInjector;
352
352
  this.scope = scope;
353
- this.normalizedProviders = staticProviders.map((provide) => {
354
- return normalizeProvider(provide);
353
+ staticProviders.forEach((provide) => {
354
+ const normalizedProvider = normalizeProvider(provide);
355
+ this.normalizedProviders.set(normalizedProvider.provide, normalizedProvider);
355
356
  });
356
357
  }
357
358
  /**
@@ -368,22 +369,20 @@ var ReflectiveInjector = class {
368
369
  throw reflectiveInjectorErrorFn(token);
369
370
  }
370
371
  if (this.recordValues.has(token)) return this.recordValues.get(token);
371
- for (let i = 0; i < this.normalizedProviders.length; i++) {
372
- const normalizedProvider = this.normalizedProviders[i];
373
- if (normalizedProvider.provide === token) return this.getValue(token, normalizedProvider);
374
- }
372
+ const normalizedProvider = this.normalizedProviders.get(token);
373
+ if (normalizedProvider) return this.getValue(token, normalizedProvider);
375
374
  if (!(token instanceof InjectionToken)) {
376
375
  const scope = getAnnotations(token).getClassMetadata(Injectable)?.metadata.provideIn;
377
376
  if (scope) {
378
377
  const normalizedProvider = normalizeProvider(token);
379
378
  if (this.scope === scope) {
380
- this.normalizedProviders.push(normalizedProvider);
379
+ this.normalizedProviders.set(normalizedProvider.provide, normalizedProvider);
381
380
  return this.getValue(token, normalizedProvider);
382
381
  }
383
382
  const parentInjector = this.parentInjector;
384
383
  if (!parentInjector || parentInjector instanceof NullInjector) {
385
384
  if (normalizedProvider.scope === "root") {
386
- this.normalizedProviders.push(normalizedProvider);
385
+ this.normalizedProviders.set(normalizedProvider.provide, normalizedProvider);
387
386
  return this.getValue(token, normalizedProvider);
388
387
  }
389
388
  if (notFoundValue !== THROW_IF_NOT_FOUND) return notFoundValue;
@@ -402,9 +401,8 @@ var ReflectiveInjector = class {
402
401
  getValue(token, normalizedProvider) {
403
402
  const { generateFactory, deps } = normalizedProvider;
404
403
  const params = this.resolveDeps(deps);
405
- let value = this.recordValues.get(token);
406
- if (value) return value;
407
- value = generateFactory(this, (token, value) => {
404
+ if (this.recordValues.has(token)) return this.recordValues.get(token);
405
+ const value = generateFactory(this, (token, value) => {
408
406
  this.recordValues.set(token, value);
409
407
  })(...params);
410
408
  this.recordValues.set(token, value);
@@ -524,8 +522,9 @@ function hasOwn(target, key) {
524
522
  //#region src/base/dep.ts
525
523
  var Dep = class {
526
524
  destroyCallbacks = [];
527
- constructor(effect) {
525
+ constructor(effect, flushMode = "sync") {
528
526
  this.effect = effect;
527
+ this.flushMode = flushMode;
529
528
  }
530
529
  destroy() {
531
530
  this.destroyCallbacks.forEach((callback) => callback());
@@ -534,7 +533,7 @@ var Dep = class {
534
533
  };
535
534
  var deps = [];
536
535
  function getDepContext() {
537
- return deps.at(-1);
536
+ return deps[deps.length - 1];
538
537
  }
539
538
  function pushDepContext(dep) {
540
539
  deps.push(dep);
@@ -545,6 +544,47 @@ function popDepContext() {
545
544
  //#endregion
546
545
  //#region src/reactive/effect.ts
547
546
  var subscribers = /* @__PURE__ */ new WeakMap();
547
+ var pendingDeps = /* @__PURE__ */ new Set();
548
+ var isFlushScheduled = false;
549
+ var effectErrorFn = makeError("Effect");
550
+ function scheduleDep(dep) {
551
+ if (dep.flushMode === "sync") {
552
+ dep.effect();
553
+ return;
554
+ }
555
+ pendingDeps.add(dep);
556
+ if (!isFlushScheduled) {
557
+ isFlushScheduled = true;
558
+ queueMicrotask(flushPendingDeps);
559
+ }
560
+ }
561
+ function flushPendingDeps() {
562
+ try {
563
+ while (pendingDeps.size > 0) {
564
+ const deps = Array.from(pendingDeps);
565
+ pendingDeps.clear();
566
+ deps.forEach((dep) => {
567
+ dep.effect();
568
+ });
569
+ }
570
+ } finally {
571
+ isFlushScheduled = false;
572
+ if (pendingDeps.size > 0) {
573
+ isFlushScheduled = true;
574
+ queueMicrotask(flushPendingDeps);
575
+ }
576
+ }
577
+ }
578
+ function nextTick() {
579
+ return Promise.resolve();
580
+ }
581
+ /**
582
+ * 同步清空响应式调度队列。
583
+ * @internal 仅用于框架内部桥接与测试控制,不建议业务代码使用。
584
+ */
585
+ function flushReactiveEffectsSync() {
586
+ flushPendingDeps();
587
+ }
548
588
  function getSubscriber(target) {
549
589
  let subscriber = subscribers.get(target);
550
590
  if (!subscriber) {
@@ -564,9 +604,17 @@ var TriggerOpTypes = /* @__PURE__ */ function(TriggerOpTypes) {
564
604
  TriggerOpTypes["Add"] = "Add";
565
605
  TriggerOpTypes["Delete"] = "Delete";
566
606
  TriggerOpTypes["Clear"] = "Clear";
607
+ TriggerOpTypes["Iterate"] = "Iterate";
567
608
  return TriggerOpTypes;
568
609
  }({});
569
610
  var unKnownKey = Symbol("unKnownKey");
611
+ function cleanupEmptyEffects(target, type, key, effects, record, subscriber) {
612
+ if (effects.size > 0) return;
613
+ record.delete(key);
614
+ if (record.size > 0) return;
615
+ subscriber.delete(type);
616
+ if (subscriber.size === 0) subscribers.delete(target);
617
+ }
570
618
  function track(target, type, key = unKnownKey) {
571
619
  const dep = getDepContext();
572
620
  if (dep) {
@@ -582,10 +630,12 @@ function track(target, type, key = unKnownKey) {
582
630
  record.set(key, effects);
583
631
  dep.destroyCallbacks.push(() => {
584
632
  effects.delete(dep);
633
+ cleanupEmptyEffects(target, type, key, effects, record, subscriber);
585
634
  });
586
635
  } else if (!effects.has(dep)) {
587
636
  dep.destroyCallbacks.push(() => {
588
637
  effects.delete(dep);
638
+ cleanupEmptyEffects(target, type, key, effects, record, subscriber);
589
639
  });
590
640
  effects.add(dep);
591
641
  }
@@ -594,23 +644,105 @@ function track(target, type, key = unKnownKey) {
594
644
  function runEffect(key, record) {
595
645
  if (!record) return;
596
646
  const effects = record.get(key);
597
- if (effects) [...effects].forEach((i) => i.effect());
647
+ if (effects) [...effects].forEach((dep) => scheduleDep(dep));
648
+ }
649
+ function collectAllEffects(record, effectSet) {
650
+ if (!record) return;
651
+ record.forEach((effects) => {
652
+ effects.forEach((effect) => {
653
+ effectSet.add(effect);
654
+ });
655
+ });
598
656
  }
599
657
  function trigger(target, type, key = unKnownKey) {
600
- const subscriber = getSubscriber(target);
601
- if (subscriber) switch (type) {
602
- case TriggerOpTypes.Set:
603
- if (isArray(target)) runEffect(unKnownKey, subscriber.get(TrackOpTypes.Iterate));
658
+ const subscriber = subscribers.get(target);
659
+ if (!subscriber) return;
660
+ if (isArray(target)) {
661
+ switch (type) {
662
+ case TriggerOpTypes.Set:
663
+ runEffect(key, subscriber.get(TrackOpTypes.Get));
664
+ runEffect(key, subscriber.get(TrackOpTypes.Has));
665
+ break;
666
+ case TriggerOpTypes.Iterate:
667
+ runEffect(key, subscriber.get(TrackOpTypes.Iterate));
668
+ break;
669
+ case TriggerOpTypes.Delete:
670
+ runEffect(key, subscriber.get(TrackOpTypes.Get));
671
+ runEffect(key, subscriber.get(TrackOpTypes.Has));
672
+ break;
673
+ default: throw effectErrorFn(`trigger: type '${type}' is not supported`);
674
+ }
675
+ return;
676
+ }
677
+ if (target instanceof Map || target instanceof WeakMap) {
678
+ switch (type) {
679
+ case TriggerOpTypes.Set:
680
+ case TriggerOpTypes.Add:
681
+ runEffect(key, subscriber.get(TrackOpTypes.Get));
682
+ runEffect(key, subscriber.get(TrackOpTypes.Has));
683
+ break;
684
+ case TriggerOpTypes.Iterate:
685
+ runEffect(key, subscriber.get(TrackOpTypes.Iterate));
686
+ break;
687
+ case TriggerOpTypes.Delete:
688
+ runEffect(key, subscriber.get(TrackOpTypes.Get));
689
+ runEffect(key, subscriber.get(TrackOpTypes.Has));
690
+ runEffect(key, subscriber.get(TrackOpTypes.Iterate));
691
+ break;
692
+ case TriggerOpTypes.Clear: {
693
+ const effects = /* @__PURE__ */ new Set();
694
+ collectAllEffects(subscriber.get(TrackOpTypes.Get), effects);
695
+ collectAllEffects(subscriber.get(TrackOpTypes.Has), effects);
696
+ collectAllEffects(subscriber.get(TrackOpTypes.Iterate), effects);
697
+ effects.forEach((effect) => scheduleDep(effect));
698
+ break;
699
+ }
700
+ default: throw effectErrorFn(`trigger: type '${type}' is not supported`);
701
+ }
702
+ return;
703
+ }
704
+ if (target instanceof Set || target instanceof WeakSet) {
705
+ switch (type) {
706
+ case TriggerOpTypes.Add:
707
+ runEffect(key, subscriber.get(TrackOpTypes.Get));
708
+ runEffect(key, subscriber.get(TrackOpTypes.Has));
709
+ break;
710
+ case TriggerOpTypes.Iterate:
711
+ runEffect(key, subscriber.get(TrackOpTypes.Iterate));
712
+ break;
713
+ case TriggerOpTypes.Delete:
714
+ runEffect(key, subscriber.get(TrackOpTypes.Get));
715
+ runEffect(key, subscriber.get(TrackOpTypes.Has));
716
+ runEffect(key, subscriber.get(TrackOpTypes.Iterate));
717
+ break;
718
+ case TriggerOpTypes.Clear: {
719
+ const effects = /* @__PURE__ */ new Set();
720
+ collectAllEffects(subscriber.get(TrackOpTypes.Get), effects);
721
+ collectAllEffects(subscriber.get(TrackOpTypes.Has), effects);
722
+ collectAllEffects(subscriber.get(TrackOpTypes.Iterate), effects);
723
+ effects.forEach((effect) => scheduleDep(effect));
724
+ break;
725
+ }
726
+ default: throw effectErrorFn(`trigger: type '${type}' is not supported`);
727
+ }
728
+ return;
729
+ }
730
+ switch (type) {
731
+ case TriggerOpTypes.Add:
604
732
  runEffect(key, subscriber.get(TrackOpTypes.Get));
605
733
  runEffect(key, subscriber.get(TrackOpTypes.Has));
606
734
  break;
607
- case TriggerOpTypes.Add:
608
- case TriggerOpTypes.Clear:
735
+ case TriggerOpTypes.Set:
736
+ runEffect(key, subscriber.get(TrackOpTypes.Get));
737
+ break;
609
738
  case TriggerOpTypes.Delete:
610
- runEffect(unKnownKey, subscriber.get(TrackOpTypes.Iterate));
611
- runEffect(key, subscriber.get(TrackOpTypes.Has));
612
739
  runEffect(key, subscriber.get(TrackOpTypes.Get));
740
+ runEffect(key, subscriber.get(TrackOpTypes.Has));
741
+ break;
742
+ case TriggerOpTypes.Iterate:
743
+ runEffect(key, subscriber.get(TrackOpTypes.Iterate));
613
744
  break;
745
+ default: throw effectErrorFn(`trigger: type '${type}' is not supported`);
614
746
  }
615
747
  }
616
748
  //#endregion
@@ -639,8 +771,8 @@ function createIterableIterator(wrapper) {
639
771
  function applyPredicateMethod(self, methodName, predicate, wrapper, thisArg) {
640
772
  const target = toRaw(self);
641
773
  track(target, TrackOpTypes.Iterate);
642
- return target[methodName]((value, index, array) => {
643
- return predicate.call(target, wrapper(value), index, array);
774
+ return target[methodName]((value, index) => {
775
+ return predicate.call(thisArg, wrapper(value), index, self);
644
776
  }, thisArg);
645
777
  }
646
778
  function applySearchMethod(self, methodName, args) {
@@ -648,11 +780,14 @@ function applySearchMethod(self, methodName, args) {
648
780
  track(target, TrackOpTypes.Iterate);
649
781
  return target[methodName](...args.map(toRaw));
650
782
  }
783
+ function triggerArrayByRange(target, startIndex, endIndex) {
784
+ for (; startIndex < endIndex; startIndex++) trigger(target, TriggerOpTypes.Set, startIndex + "");
785
+ }
651
786
  function createArrayHandlers(wrapper) {
652
787
  return {
653
788
  concat(...items) {
654
789
  const target = toRaw(this);
655
- trigger(target, TriggerOpTypes.Add);
790
+ track(target, TrackOpTypes.Iterate);
656
791
  return target.concat(...items);
657
792
  },
658
793
  every(predicate, thisArg) {
@@ -695,13 +830,23 @@ function createArrayHandlers(wrapper) {
695
830
  },
696
831
  pop() {
697
832
  const target = toRaw(this);
698
- trigger(target, TriggerOpTypes.Delete);
699
- return target.pop();
833
+ const oldLength = target.length;
834
+ const value = target.pop();
835
+ const newLength = target.length;
836
+ if (newLength < oldLength) {
837
+ trigger(target, TriggerOpTypes.Set, newLength + "");
838
+ trigger(target, TriggerOpTypes.Set, "length");
839
+ trigger(target, TriggerOpTypes.Iterate);
840
+ }
841
+ return value;
700
842
  },
701
843
  push(...items) {
702
844
  const target = toRaw(this);
703
- trigger(target, TriggerOpTypes.Add);
704
- return target.push(...items);
845
+ const oldLength = target.length;
846
+ const length = target.push(...items);
847
+ triggerArrayByRange(target, oldLength, length);
848
+ trigger(target, TriggerOpTypes.Iterate);
849
+ return length;
705
850
  },
706
851
  reduce(callbackFn, ...args) {
707
852
  const target = toRaw(this);
@@ -721,18 +866,27 @@ function createArrayHandlers(wrapper) {
721
866
  },
722
867
  shift() {
723
868
  const target = toRaw(this);
724
- trigger(target, TriggerOpTypes.Delete);
725
- return target.shift();
869
+ const oldLength = target.length;
870
+ const value = target.shift();
871
+ if (target.length < oldLength) {
872
+ triggerArrayByRange(target, 0, oldLength);
873
+ trigger(target, TriggerOpTypes.Set, "length");
874
+ trigger(target, TriggerOpTypes.Iterate);
875
+ }
876
+ return value;
726
877
  },
727
878
  some(predicate, thisArg) {
728
879
  return applyPredicateMethod(this, "some", predicate, wrapper, thisArg);
729
880
  },
730
- splice(start, deleteCount) {
881
+ splice(start, ...items) {
731
882
  const target = toRaw(this);
732
- trigger(target, TriggerOpTypes.Set);
733
- trigger(target, TriggerOpTypes.Add);
734
- trigger(target, TriggerOpTypes.Delete);
735
- return target.splice(start, deleteCount).map((i) => wrapper(i));
883
+ const oldLength = target.length;
884
+ const deleted = target.splice(start, ...items).map((i) => wrapper(i));
885
+ const newLength = target.length;
886
+ triggerArrayByRange(target, start, Math.max(oldLength, newLength));
887
+ if (oldLength !== newLength) trigger(target, TriggerOpTypes.Set, "length");
888
+ trigger(target, TriggerOpTypes.Iterate);
889
+ return deleted;
736
890
  },
737
891
  toReversed() {
738
892
  const target = toRaw(this);
@@ -751,8 +905,11 @@ function createArrayHandlers(wrapper) {
751
905
  },
752
906
  unshift(...items) {
753
907
  const target = toRaw(this);
754
- trigger(target, TriggerOpTypes.Add);
755
- return target.unshift(...items);
908
+ const length = target.unshift(...items);
909
+ triggerArrayByRange(target, 0, length);
910
+ trigger(target, TriggerOpTypes.Set, "length");
911
+ trigger(target, TriggerOpTypes.Iterate);
912
+ return length;
756
913
  },
757
914
  [Symbol.iterator]() {
758
915
  return this.values();
@@ -765,6 +922,7 @@ function createArrayHandlers(wrapper) {
765
922
  function createMapHandlers(wrapper) {
766
923
  return {
767
924
  get(key) {
925
+ key = toRaw(key);
768
926
  const target = toRaw(this);
769
927
  track(target, TrackOpTypes.Get, key);
770
928
  return wrapper(target.get(key));
@@ -774,8 +932,11 @@ function createMapHandlers(wrapper) {
774
932
  key = toRaw(key);
775
933
  value = toRaw(value);
776
934
  const has = target.has(key);
935
+ const oldValue = has ? target.get(key) : void 0;
936
+ if (has && Object.is(oldValue, value)) return this;
777
937
  const r = target.set(key, value);
778
938
  trigger(target, has ? TriggerOpTypes.Set : TriggerOpTypes.Add, key);
939
+ if (!has) trigger(target, TriggerOpTypes.Iterate);
779
940
  return r;
780
941
  },
781
942
  has(key) {
@@ -789,19 +950,21 @@ function createMapHandlers(wrapper) {
789
950
  key = toRaw(key);
790
951
  const r = target.delete(key);
791
952
  trigger(target, TriggerOpTypes.Delete, key);
953
+ if (r) trigger(target, TriggerOpTypes.Iterate);
792
954
  return r;
793
955
  },
794
956
  forEach(callbackFn, thisArg) {
795
957
  const target = toRaw(this);
796
- track(target, TrackOpTypes.Iterate, void 0);
958
+ track(target, TrackOpTypes.Iterate);
797
959
  target.forEach((v, k, m) => {
798
- callbackFn.call(this, wrapper(v), wrapper(k), m);
960
+ callbackFn.call(thisArg, wrapper(v), wrapper(k), m);
799
961
  }, thisArg);
800
962
  },
801
963
  clear() {
802
964
  const target = toRaw(this);
965
+ if (target.size === 0) return;
803
966
  target.clear();
804
- trigger(target, TriggerOpTypes.Clear, void 0);
967
+ trigger(target, TriggerOpTypes.Clear);
805
968
  },
806
969
  [Symbol.iterator]() {
807
970
  return this.entries();
@@ -818,16 +981,19 @@ function createSetHandlers(wrapper) {
818
981
  value = toRaw(value);
819
982
  if (!target.has(value)) {
820
983
  target.add(value);
821
- trigger(target, TriggerOpTypes.Add, void 0);
984
+ trigger(target, TriggerOpTypes.Add, value);
985
+ trigger(target, TriggerOpTypes.Iterate);
822
986
  }
823
987
  return this;
824
988
  },
825
989
  delete(value) {
826
990
  const target = toRaw(this);
827
991
  value = toRaw(value);
828
- const has = target.has(value);
829
992
  const b = target.delete(value);
830
- if (!has) trigger(target, TriggerOpTypes.Delete, void 0);
993
+ if (b) {
994
+ trigger(target, TriggerOpTypes.Delete, value);
995
+ trigger(target, TriggerOpTypes.Iterate);
996
+ }
831
997
  return b;
832
998
  },
833
999
  has(key) {
@@ -838,16 +1004,16 @@ function createSetHandlers(wrapper) {
838
1004
  },
839
1005
  forEach(callbackFn, thisArg) {
840
1006
  const target = toRaw(this);
841
- track(target, TrackOpTypes.Iterate, void 0);
1007
+ track(target, TrackOpTypes.Iterate);
842
1008
  target.forEach((v, k, m) => {
843
- callbackFn.call(this, wrapper(v), wrapper(k), m);
1009
+ callbackFn.call(thisArg, wrapper(v), wrapper(k), m);
844
1010
  }, thisArg);
845
1011
  },
846
1012
  clear() {
847
1013
  const target = toRaw(this);
848
1014
  if (target.size !== 0) {
849
1015
  target.clear();
850
- trigger(target, TriggerOpTypes.Clear, void 0);
1016
+ trigger(target, TriggerOpTypes.Clear);
851
1017
  }
852
1018
  },
853
1019
  [Symbol.iterator]() {
@@ -861,6 +1027,8 @@ function createSetHandlers(wrapper) {
861
1027
  var reactiveErrorFn = makeError("reactive");
862
1028
  var rawToProxyCache = /* @__PURE__ */ new WeakMap();
863
1029
  var proxyToRawCache = /* @__PURE__ */ new WeakMap();
1030
+ var shallowRawToProxyCache = /* @__PURE__ */ new WeakMap();
1031
+ var shallowProxyToRawCache = /* @__PURE__ */ new WeakMap();
864
1032
  /**
865
1033
  * 将响应式对象转换为原始对象
866
1034
  * @param value 响应式对象
@@ -876,6 +1044,7 @@ var proxyToRawCache = /* @__PURE__ */ new WeakMap();
876
1044
  */
877
1045
  function toRaw(value) {
878
1046
  if (proxyToRawCache.has(value)) return proxyToRawCache.get(value);
1047
+ if (shallowProxyToRawCache.has(value)) return shallowProxyToRawCache.get(value);
879
1048
  return value;
880
1049
  }
881
1050
  /**
@@ -892,18 +1061,24 @@ function toRaw(value) {
892
1061
  * ```
893
1062
  */
894
1063
  function isReactive(value) {
895
- return proxyToRawCache.has(value);
1064
+ return proxyToRawCache.has(value) || shallowProxyToRawCache.has(value);
1065
+ }
1066
+ var internalWriteDepth = 0;
1067
+ function isInternalWriting() {
1068
+ return internalWriteDepth > 0;
896
1069
  }
897
- var fromInternalWrite = false;
898
1070
  /**
899
1071
  * 内部写入,用于避免类型为只读的响应式对象写入报错
900
1072
  * @param fn 要执行的函数
901
1073
  * @internal
902
1074
  */
903
1075
  function internalWrite(fn) {
904
- fromInternalWrite = true;
905
- fn();
906
- fromInternalWrite = false;
1076
+ internalWriteDepth++;
1077
+ try {
1078
+ fn();
1079
+ } finally {
1080
+ internalWriteDepth--;
1081
+ }
907
1082
  }
908
1083
  var ObjectReactiveHandler = class {
909
1084
  isShallow;
@@ -913,32 +1088,44 @@ var ObjectReactiveHandler = class {
913
1088
  this.isShallow = config.shallow;
914
1089
  }
915
1090
  set(target, p, newValue, receiver) {
916
- if (this.isReadonly && !fromInternalWrite) throw reactiveErrorFn("Object is readonly!");
1091
+ if (this.isReadonly && !isInternalWriting()) throw reactiveErrorFn("Object is readonly!");
917
1092
  const rawValue = toRaw(newValue);
918
1093
  const oldValue = target[p];
919
1094
  const v = this.isShallow ? newValue : rawValue;
920
- if (oldValue === rawValue) return Reflect.set(target, p, v, receiver);
1095
+ if (Object.is(oldValue, rawValue)) return Reflect.set(target, p, v, receiver);
1096
+ const has = hasOwn(target, p);
921
1097
  const b = Reflect.set(target, p, v, receiver);
922
- fromInternalWrite = false;
923
- if (hasOwn(target, p)) trigger(target, TriggerOpTypes.Set, p);
924
- else trigger(target, TriggerOpTypes.Add, p);
1098
+ if (has) trigger(target, TriggerOpTypes.Set, p);
1099
+ else {
1100
+ trigger(target, TriggerOpTypes.Add, p);
1101
+ trigger(target, TriggerOpTypes.Iterate);
1102
+ }
925
1103
  return b;
926
1104
  }
927
1105
  get(target, p, receiver) {
928
1106
  track(target, TrackOpTypes.Get, p);
929
1107
  const value = Reflect.get(target, p, receiver);
930
- if (this.isShallow) return value;
1108
+ if (this.isShallow || !value || typeof value !== "object") return value;
931
1109
  return reactive(value);
932
1110
  }
933
1111
  deleteProperty(target, p) {
1112
+ if (this.isReadonly && !isInternalWriting()) throw reactiveErrorFn("Object is readonly!");
1113
+ const has = hasOwn(target, p);
934
1114
  const b = Reflect.deleteProperty(target, p);
935
- trigger(target, TriggerOpTypes.Delete, p);
1115
+ if (b && has) {
1116
+ trigger(target, TriggerOpTypes.Delete, p);
1117
+ trigger(target, TriggerOpTypes.Iterate);
1118
+ }
936
1119
  return b;
937
1120
  }
938
1121
  ownKeys(target) {
939
1122
  track(target, TrackOpTypes.Iterate);
940
1123
  return Reflect.ownKeys(target);
941
1124
  }
1125
+ has(target, p) {
1126
+ track(target, TrackOpTypes.Has, p);
1127
+ return Reflect.has(target, p);
1128
+ }
942
1129
  };
943
1130
  function noReactive(v) {
944
1131
  return v;
@@ -950,8 +1137,41 @@ var ArrayReactiveHandler = class extends ObjectReactiveHandler {
950
1137
  }
951
1138
  get(target, p, receiver) {
952
1139
  if (Reflect.has(this.interceptors, p) && p in target) return this.interceptors[p];
1140
+ if (p === "length") {
1141
+ track(target, TrackOpTypes.Iterate);
1142
+ return Reflect.get(target, p, receiver);
1143
+ }
953
1144
  return super.get(target, p, receiver);
954
1145
  }
1146
+ set(target, p, newValue, receiver) {
1147
+ if (this.isReadonly && !isInternalWriting()) throw reactiveErrorFn("Object is readonly!");
1148
+ if (p === "length") {
1149
+ const oldLength = target.length;
1150
+ const b = super.set(target, p, newValue, receiver);
1151
+ const newLength = target.length;
1152
+ if (newLength < oldLength) triggerArrayByRange(target, newLength, oldLength);
1153
+ if (oldLength !== newLength) trigger(target, TriggerOpTypes.Iterate);
1154
+ return b;
1155
+ }
1156
+ const rawValue = toRaw(newValue);
1157
+ const oldValue = target[p];
1158
+ const v = this.isShallow ? newValue : rawValue;
1159
+ if (Object.is(oldValue, rawValue)) return Reflect.set(target, p, v, receiver);
1160
+ const oldLength = target.length;
1161
+ const b = Reflect.set(target, p, v, receiver);
1162
+ const newLength = target.length;
1163
+ trigger(target, TriggerOpTypes.Set, p);
1164
+ trigger(target, TriggerOpTypes.Iterate);
1165
+ if (newLength > oldLength) trigger(target, TriggerOpTypes.Set, "length");
1166
+ return b;
1167
+ }
1168
+ deleteProperty(target, p) {
1169
+ if (this.isReadonly && !isInternalWriting()) throw reactiveErrorFn("Object is readonly!");
1170
+ const has = hasOwn(target, p);
1171
+ const b = Reflect.deleteProperty(target, p);
1172
+ if (b && has) trigger(target, TriggerOpTypes.Delete, p);
1173
+ return b;
1174
+ }
955
1175
  };
956
1176
  var MapReactiveHandler = class extends ObjectReactiveHandler {
957
1177
  interceptors = createMapHandlers(this.isShallow ? noReactive : reactive);
@@ -961,7 +1181,7 @@ var MapReactiveHandler = class extends ObjectReactiveHandler {
961
1181
  get(target, p, receiver) {
962
1182
  if (Reflect.has(this.interceptors, p) && p in target) return this.interceptors[p];
963
1183
  if (p === "size") {
964
- track(target, TrackOpTypes.Iterate, p);
1184
+ track(target, TrackOpTypes.Iterate);
965
1185
  return Reflect.get(target, p);
966
1186
  }
967
1187
  return super.get(target, p, receiver);
@@ -975,7 +1195,7 @@ var SetReactiveHandler = class extends ObjectReactiveHandler {
975
1195
  get(target, p, receiver) {
976
1196
  if (Reflect.has(this.interceptors, p) && p in target) return this.interceptors[p];
977
1197
  if (p === "size") {
978
- track(target, TrackOpTypes.Iterate, p);
1198
+ track(target, TrackOpTypes.Iterate);
979
1199
  return Reflect.get(target, p);
980
1200
  }
981
1201
  return super.get(target, p, receiver);
@@ -1063,17 +1283,9 @@ function hasChange(newProps, oldProps) {
1063
1283
  return false;
1064
1284
  }
1065
1285
  function comparePropsWithCallbacks(oldProps, newProps, onDeleted, onAdded, onUpdated) {
1066
- const oldKeys = Object.keys(oldProps);
1067
- for (let i = 0; i < oldKeys.length; i++) {
1068
- const key = oldKeys[i];
1069
- if (!(key in newProps)) onDeleted(key, oldProps[key]);
1070
- }
1071
- const newKeys = Object.keys(newProps);
1072
- for (let i = 0; i < newKeys.length; i++) {
1073
- const key = newKeys[i];
1074
- if (!(key in oldProps)) onAdded(key, newProps[key]);
1075
- else if (oldProps[key] !== newProps[key]) onUpdated(key, newProps[key], oldProps[key]);
1076
- }
1286
+ for (const key in oldProps) if (!(key in newProps)) onDeleted(key, oldProps[key]);
1287
+ for (const key in newProps) if (!(key in oldProps)) onAdded(key, newProps[key]);
1288
+ else if (oldProps[key] !== newProps[key]) onUpdated(key, newProps[key], oldProps[key]);
1077
1289
  }
1078
1290
  function classToString(config) {
1079
1291
  if (typeof config === "string") return config;
@@ -1127,6 +1339,30 @@ var refErrorFn = makeError("Ref");
1127
1339
  * }
1128
1340
  * }
1129
1341
  * ```
1342
+ * @example
1343
+ * ```tsx
1344
+ * function Child() {
1345
+ * return {
1346
+ * show() {
1347
+ * console.log('show')
1348
+ * },
1349
+ * render() {
1350
+ * return <div>child</div>
1351
+ * }
1352
+ * }
1353
+ * }
1354
+ * function App() {
1355
+ * const ref = createDynamicRef<typeof Child>((child) => {
1356
+ * child.show()
1357
+ * return () => {
1358
+ * console.log('destroy')
1359
+ * }
1360
+ * })
1361
+ * return () => {
1362
+ * return <Child ref={ref}/>
1363
+ * }
1364
+ * }
1365
+ * ```
1130
1366
  */
1131
1367
  function createDynamicRef(effect) {
1132
1368
  return effect;
@@ -1147,6 +1383,28 @@ function createDynamicRef(effect) {
1147
1383
  * }
1148
1384
  * }
1149
1385
  * ```
1386
+ * @example
1387
+ * ```tsx
1388
+ * function Child() {
1389
+ * return {
1390
+ * show() {
1391
+ * console.log('show')
1392
+ * },
1393
+ * render() {
1394
+ * return <div>child</div>
1395
+ * }
1396
+ * }
1397
+ * }
1398
+ * function App() {
1399
+ * const ref = createRef<typeof Child>()
1400
+ * onMounted(() => {
1401
+ * ref.value?.show()
1402
+ * })
1403
+ * return () => {
1404
+ * return <Child ref={ref}/>
1405
+ * }
1406
+ * }
1407
+ * ```
1150
1408
  */
1151
1409
  function createRef() {
1152
1410
  return createShallowReadonlyProxy({ value: null });
@@ -1236,7 +1494,7 @@ var Component = class {
1236
1494
  this.refEffects = /* @__PURE__ */ new Map();
1237
1495
  this.listener = new Dep(() => {
1238
1496
  this.markAsDirtied();
1239
- });
1497
+ }, "async");
1240
1498
  }
1241
1499
  markAsDirtied() {
1242
1500
  this._dirty = true;
@@ -1252,7 +1510,7 @@ var Component = class {
1252
1510
  componentSetupStack.push(this);
1253
1511
  const render = this.type(this.props);
1254
1512
  const isRenderFn = typeof render === "function";
1255
- this.instance = isRenderFn ? { $render: render } : render;
1513
+ this.instance = isRenderFn ? { render } : render;
1256
1514
  onMounted(() => {
1257
1515
  applyRefs(this.props.ref, this.instance, this.refEffects);
1258
1516
  return () => {
@@ -1263,9 +1521,9 @@ var Component = class {
1263
1521
  });
1264
1522
  componentSetupStack.pop();
1265
1523
  pushDepContext(this.listener);
1266
- const template = this.instance.$render();
1524
+ const template = this.instance.render();
1267
1525
  popDepContext();
1268
- update(template, this.instance.$portalHost);
1526
+ update(template);
1269
1527
  this.rendered();
1270
1528
  }
1271
1529
  updateProps(newProps) {
@@ -1290,7 +1548,7 @@ var Component = class {
1290
1548
  rerender() {
1291
1549
  this.listener.destroy();
1292
1550
  pushDepContext(this.listener);
1293
- const template = this.instance.$render();
1551
+ const template = this.instance.render();
1294
1552
  popDepContext();
1295
1553
  return template;
1296
1554
  }
@@ -1373,6 +1631,18 @@ function registryComponentDestroyCallback(fn) {
1373
1631
  }
1374
1632
  }
1375
1633
  //#endregion
1634
+ //#region src/base/_render-context.ts
1635
+ var containerStack = [];
1636
+ function pushContainer(container) {
1637
+ containerStack.push(container);
1638
+ }
1639
+ function popContainer() {
1640
+ containerStack.pop();
1641
+ }
1642
+ function getContainer() {
1643
+ return containerStack[containerStack.length - 1];
1644
+ }
1645
+ //#endregion
1376
1646
  //#region src/base/jsx-element.ts
1377
1647
  function Fragment(props) {
1378
1648
  return () => {
@@ -1410,8 +1680,8 @@ function withMark(marks, setup) {
1410
1680
  if (typeof componentRenderFn === "function") return function() {
1411
1681
  return applyMark(marks, componentRenderFn);
1412
1682
  };
1413
- const oldRender = componentRenderFn.$render;
1414
- componentRenderFn.$render = function() {
1683
+ const oldRender = componentRenderFn.render;
1684
+ componentRenderFn.render = function() {
1415
1685
  return applyMark(marks, () => {
1416
1686
  return oldRender.call(componentRenderFn);
1417
1687
  });
@@ -1450,7 +1720,7 @@ function applyMark(mark, render) {
1450
1720
  * return () => {
1451
1721
  * return (
1452
1722
  * <div>
1453
- * <Portal host={modal}>
1723
+ * <Portal container={modal}>
1454
1724
  * 这里的内容将渲染到 modal 节点
1455
1725
  * </Portal>
1456
1726
  * </div>
@@ -1460,12 +1730,10 @@ function applyMark(mark, render) {
1460
1730
  * ```
1461
1731
  */
1462
1732
  function Portal(props) {
1463
- return {
1464
- $portalHost: props.host,
1465
- $render() {
1466
- return props.children;
1467
- }
1468
- };
1733
+ return { render() {
1734
+ pushContainer(props.container);
1735
+ return props.children;
1736
+ } };
1469
1737
  }
1470
1738
  //#endregion
1471
1739
  //#region src/reactive/watch-effect.ts
@@ -1478,12 +1746,18 @@ function Portal(props) {
1478
1746
  function watchEffect(effect) {
1479
1747
  const dep = new Dep(function() {
1480
1748
  pushDepContext(dep);
1749
+ try {
1750
+ effect();
1751
+ } finally {
1752
+ popDepContext();
1753
+ }
1754
+ }, "async");
1755
+ pushDepContext(dep);
1756
+ try {
1481
1757
  effect();
1758
+ } finally {
1482
1759
  popDepContext();
1483
- });
1484
- pushDepContext(dep);
1485
- effect();
1486
- popDepContext();
1760
+ }
1487
1761
  function unWatch() {
1488
1762
  dep.destroy();
1489
1763
  }
@@ -1508,7 +1782,7 @@ function watch(trigger, callback) {
1508
1782
  return;
1509
1783
  }
1510
1784
  const newValue = trigger();
1511
- if (newValue !== oldValue) {
1785
+ if (!Object.is(newValue, oldValue)) {
1512
1786
  callback(newValue, oldValue);
1513
1787
  oldValue = newValue;
1514
1788
  }
@@ -1673,7 +1947,7 @@ var listenerReg = /^on[A-Z]/;
1673
1947
  var nativeNodeRefRecord = /* @__PURE__ */ new WeakMap();
1674
1948
  function createRenderer(component, nativeRenderer, namespace) {
1675
1949
  let isInit = true;
1676
- return function render(host) {
1950
+ return function render(container) {
1677
1951
  if (isInit) {
1678
1952
  isInit = false;
1679
1953
  componentRender(nativeRenderer, component, {
@@ -1687,8 +1961,8 @@ function createRenderer(component, nativeRenderer, namespace) {
1687
1961
  namespace
1688
1962
  }, {
1689
1963
  isParent: true,
1690
- host,
1691
- rootHost: host
1964
+ container,
1965
+ rootContainer: container
1692
1966
  });
1693
1967
  } else deepUpdateByComponentDirtyTree(nativeRenderer, component, false);
1694
1968
  };
@@ -1710,23 +1984,40 @@ function buildElementChildren(atom, nativeRenderer, parentComponent, context) {
1710
1984
  }
1711
1985
  }
1712
1986
  function patchComponent(nativeRenderer, component, oldChildAtom, newAtom, context, needMove) {
1713
- newAtom.child = createChildChain(component.rerender(), nativeRenderer, newAtom.namespace);
1987
+ const oldContainer = component.viewMetadata.container;
1988
+ const expectContainer = component.viewMetadata.expectContainer;
1989
+ const newTemplate = component.rerender();
1990
+ const portalContainer = getContainer();
1991
+ popContainer();
1992
+ if (portalContainer && portalContainer !== expectContainer) context = {
1993
+ isParent: true,
1994
+ container: portalContainer,
1995
+ rootContainer: portalContainer
1996
+ };
1997
+ component.viewMetadata = {
1998
+ atom: newAtom,
1999
+ expectContainer,
2000
+ ...context
2001
+ };
2002
+ if (oldContainer !== context.container) needMove = true;
2003
+ newAtom.child = createChildChain(newTemplate, nativeRenderer, newAtom.namespace);
1714
2004
  diff(nativeRenderer, component, newAtom.child, oldChildAtom, context, needMove);
2005
+ return context;
1715
2006
  }
1716
2007
  function deepUpdateByComponentDirtyTree(nativeRenderer, component, needMove) {
1717
2008
  if (component.dirty) {
1718
- const { atom, host, isParent, rootHost } = component.viewMetadata;
2009
+ const { atom, container, isParent, rootContainer } = component.viewMetadata;
1719
2010
  const context = {
1720
- host,
2011
+ container,
1721
2012
  isParent,
1722
- rootHost
2013
+ rootContainer
1723
2014
  };
1724
2015
  const diffAtom = atom.child;
1725
2016
  patchComponent(nativeRenderer, component, diffAtom, atom, context, needMove);
1726
2017
  const next = atom.sibling;
1727
2018
  if (next && next.jsxNode instanceof Component) {
1728
2019
  const view = next.jsxNode.viewMetadata;
1729
- view.host = context.host;
2020
+ view.container = context.container;
1730
2021
  view.isParent = context.isParent;
1731
2022
  }
1732
2023
  component.rendered();
@@ -1737,85 +2028,24 @@ function deepUpdateByComponentDirtyTree(nativeRenderer, component, needMove) {
1737
2028
  component.rendered();
1738
2029
  }
1739
2030
  }
1740
- function createOldAtomMatcher(oldAtoms) {
1741
- const typeMap = /* @__PURE__ */ new Map();
1742
- const cursorMap = /* @__PURE__ */ new WeakMap();
1743
- for (let i = 0; i < oldAtoms.length; i++) {
1744
- const atom = oldAtoms[i];
1745
- let nodeTypeMap = typeMap.get(atom.type);
1746
- if (!nodeTypeMap) {
1747
- nodeTypeMap = /* @__PURE__ */ new Map();
1748
- typeMap.set(atom.type, nodeTypeMap);
1749
- }
1750
- let keyMap = nodeTypeMap.get(atom.nodeType);
1751
- if (!keyMap) {
1752
- keyMap = /* @__PURE__ */ new Map();
1753
- nodeTypeMap.set(atom.nodeType, keyMap);
1754
- }
1755
- const key = atom.key;
1756
- const indices = keyMap.get(key);
1757
- if (indices) indices.push(i);
1758
- else keyMap.set(key, [i]);
1759
- }
1760
- const take = (atom, matched) => {
1761
- const nodeTypeMap = typeMap.get(atom.type);
1762
- if (!nodeTypeMap) return -1;
1763
- const keyMap = nodeTypeMap.get(atom.nodeType);
1764
- if (!keyMap) return -1;
1765
- const indices = keyMap.get(atom.key);
1766
- if (!indices || !indices.length) return -1;
1767
- let cursor = cursorMap.get(indices) ?? 0;
1768
- while (cursor < indices.length) {
1769
- const index = indices[cursor];
1770
- cursor++;
1771
- if (!matched[index]) {
1772
- cursorMap.set(indices, cursor);
1773
- return index;
1774
- }
1775
- }
1776
- cursorMap.set(indices, cursor);
1777
- return -1;
1778
- };
1779
- return { take };
1780
- }
1781
2031
  function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, needMove) {
1782
2032
  const commits = [];
1783
- const oldAtoms = [];
2033
+ while (newAtom) {
2034
+ oldAtom = createChanges(newAtom, oldAtom, commits);
2035
+ newAtom = newAtom.sibling;
2036
+ }
1784
2037
  let dirtyDiffAtom = oldAtom;
1785
2038
  while (dirtyDiffAtom) {
1786
- oldAtoms.push(dirtyDiffAtom);
2039
+ cleanView(nativeRenderer, dirtyDiffAtom, true);
1787
2040
  dirtyDiffAtom = dirtyDiffAtom.sibling;
1788
2041
  }
1789
- const matched = new Array(oldAtoms.length).fill(false);
1790
- const matcher = createOldAtomMatcher(oldAtoms);
1791
- const pendingDeleteIndices = [];
1792
- let cursor = newAtom;
1793
- while (cursor) {
1794
- const matchedIndex = matcher.take(cursor, matched);
1795
- if (matchedIndex >= 0) {
1796
- matched[matchedIndex] = true;
1797
- commits.push({
1798
- dirtyAtom: oldAtoms[matchedIndex],
1799
- newAtom: cursor
1800
- });
1801
- } else commits.push({
1802
- dirtyAtom: null,
1803
- newAtom: cursor
1804
- });
1805
- cursor = cursor.sibling;
1806
- }
1807
- for (let i = 0; i < oldAtoms.length; i++) if (!matched[i]) {
1808
- pendingDeleteIndices.push(i);
1809
- cleanView(nativeRenderer, oldAtoms[i], true);
1810
- }
1811
2042
  let offset = 0;
1812
- let pendingDeleteCursor = 0;
1813
2043
  const len = commits.length;
1814
2044
  for (let i = 0; i < len; i++) {
1815
- while (pendingDeleteCursor < pendingDeleteIndices.length) {
1816
- if (oldAtoms[pendingDeleteIndices[pendingDeleteCursor]].index <= i) {
2045
+ while (oldAtom) {
2046
+ if (oldAtom.index <= i) {
1817
2047
  offset--;
1818
- pendingDeleteCursor++;
2048
+ oldAtom = oldAtom.sibling;
1819
2049
  continue;
1820
2050
  }
1821
2051
  break;
@@ -1838,51 +2068,69 @@ function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, needMo
1838
2068
  }
1839
2069
  }
1840
2070
  }
2071
+ function createChanges(newAtom, oldAtom, commits) {
2072
+ const startDiffAtom = oldAtom;
2073
+ let prev = null;
2074
+ while (oldAtom) {
2075
+ if (oldAtom.type === newAtom.type && oldAtom.nodeType === newAtom.nodeType && oldAtom.key === newAtom.key) {
2076
+ commits.push({
2077
+ dirtyAtom: oldAtom,
2078
+ newAtom
2079
+ });
2080
+ const next = oldAtom.sibling;
2081
+ if (!prev) return next;
2082
+ prev.sibling = next;
2083
+ return startDiffAtom;
2084
+ }
2085
+ prev = oldAtom;
2086
+ oldAtom = oldAtom.sibling;
2087
+ }
2088
+ commits.push({
2089
+ dirtyAtom: null,
2090
+ newAtom
2091
+ });
2092
+ return startDiffAtom;
2093
+ }
1841
2094
  function updateText(nativeRenderer, context, offset, needMove, newAtom, oldAtom) {
1842
2095
  const nativeNode = oldAtom.nativeNode;
1843
2096
  newAtom.nativeNode = nativeNode;
1844
2097
  if (needMove || newAtom.index - offset !== oldAtom.index) insertNode(nativeRenderer, newAtom, context);
1845
- context.host = nativeNode;
2098
+ context.container = nativeNode;
1846
2099
  context.isParent = false;
1847
2100
  }
1848
2101
  function updateElement(nativeRenderer, context, parentComponent, offset, needMove, newAtom, oldAtom) {
1849
2102
  const nativeNode = oldAtom.nativeNode;
1850
2103
  newAtom.nativeNode = nativeNode;
1851
2104
  if (needMove || newAtom.index - offset !== oldAtom.index) insertNode(nativeRenderer, newAtom, context);
1852
- context.host = nativeNode;
2105
+ context.container = nativeNode;
1853
2106
  context.isParent = false;
1854
2107
  updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComponent, {
1855
- host: nativeNode,
2108
+ container: nativeNode,
1856
2109
  isParent: true,
1857
- rootHost: context.rootHost
2110
+ rootContainer: context.rootContainer
1858
2111
  });
1859
2112
  }
1860
2113
  function updateComponent(nativeRenderer, context, offset, needMove, newAtom, oldAtom) {
1861
2114
  const component = oldAtom.jsxNode;
1862
- const portalHost = component.instance.$portalHost;
1863
- context = portalHost ? {
1864
- isParent: true,
1865
- host: portalHost,
1866
- rootHost: portalHost
1867
- } : context;
1868
- component.viewMetadata = {
1869
- atom: newAtom,
1870
- ...context
1871
- };
1872
2115
  const newProps = newAtom.jsxNode.props;
1873
2116
  newAtom.jsxNode = component;
1874
2117
  needMove = needMove || newAtom.index - offset !== oldAtom.index;
1875
2118
  const propsIsChanged = hasChange(newProps, component.props);
1876
2119
  if (propsIsChanged) component.updateProps(newProps);
1877
2120
  if (propsIsChanged || component.dirty) {
1878
- patchComponent(nativeRenderer, component, oldAtom.child, newAtom, context, needMove);
2121
+ const updatedContext = patchComponent(nativeRenderer, component, oldAtom.child, newAtom, context, needMove);
1879
2122
  const next = oldAtom.sibling;
1880
2123
  if (next && next.jsxNode instanceof Component) {
1881
2124
  const view = next.jsxNode.viewMetadata;
1882
- view.host = context.host;
1883
- view.isParent = context.isParent;
2125
+ view.container = updatedContext.container;
2126
+ view.isParent = updatedContext.isParent;
1884
2127
  }
1885
2128
  } else {
2129
+ component.viewMetadata = {
2130
+ atom: newAtom,
2131
+ expectContainer: component.viewMetadata.expectContainer,
2132
+ ...context
2133
+ };
1886
2134
  newAtom.child = oldAtom.child;
1887
2135
  reuseComponentView(nativeRenderer, newAtom.child, context, needMove, !component.changedSubComponents.size);
1888
2136
  }
@@ -1898,7 +2146,7 @@ function reuseComponentView(nativeRenderer, child, context, moveView, skipSubCom
1898
2146
  if (moveView) insertNode(nativeRenderer, atom, context);
1899
2147
  if (!skipSubComponentDiff) reuseElementChildrenView(nativeRenderer, atom, context);
1900
2148
  context.isParent = false;
1901
- context.host = atom.nativeNode;
2149
+ context.container = atom.nativeNode;
1902
2150
  }
1903
2151
  };
1904
2152
  while (child) {
@@ -1925,7 +2173,7 @@ function cleanElementChildren(atom, nativeRenderer) {
1925
2173
  function cleanView(nativeRenderer, atom, needClean) {
1926
2174
  if (atom.type === ComponentAtomType) {
1927
2175
  const jsxNode = atom.jsxNode;
1928
- if (jsxNode.instance.$portalHost) needClean = true;
2176
+ if (jsxNode.viewMetadata.container !== jsxNode.viewMetadata.expectContainer) needClean = true;
1929
2177
  cleanChildren(atom, nativeRenderer, needClean);
1930
2178
  jsxNode.destroy();
1931
2179
  return;
@@ -1953,15 +2201,19 @@ function cleanChildren(atom, nativeRenderer, needClean) {
1953
2201
  }
1954
2202
  }
1955
2203
  function componentRender(nativeRenderer, component, from, context) {
1956
- component.render((template, portalHost) => {
2204
+ component.render((template) => {
2205
+ const portalContainer = getContainer();
2206
+ popContainer();
1957
2207
  from.child = createChildChain(template, nativeRenderer, from.namespace);
1958
- context = portalHost ? {
2208
+ const expectContainer = context.container;
2209
+ context = portalContainer && portalContainer !== context.container ? {
1959
2210
  isParent: true,
1960
- host: portalHost,
1961
- rootHost: portalHost
2211
+ container: portalContainer,
2212
+ rootContainer: portalContainer
1962
2213
  } : context;
1963
2214
  component.viewMetadata = {
1964
2215
  atom: from,
2216
+ expectContainer,
1965
2217
  ...context
1966
2218
  };
1967
2219
  let child = from.child;
@@ -2018,9 +2270,9 @@ function createChildChain(template, nativeRenderer, namespace) {
2018
2270
  return beforeAtom.sibling;
2019
2271
  }
2020
2272
  function insertNode(nativeRenderer, atom, context) {
2021
- if (context.isParent) if (context.host === context.rootHost) nativeRenderer.appendChild(context.host, atom.nativeNode, atom.namespace);
2022
- else nativeRenderer.prependChild(context.host, atom.nativeNode, atom.namespace);
2023
- else nativeRenderer.insertAfter(atom.nativeNode, context.host, atom.namespace);
2273
+ if (context.isParent) if (context.container === context.rootContainer) nativeRenderer.appendChild(context.container, atom.nativeNode, atom.namespace);
2274
+ else nativeRenderer.prependChild(context.container, atom.nativeNode, atom.namespace);
2275
+ else nativeRenderer.insertAfter(atom.nativeNode, context.container, atom.namespace);
2024
2276
  }
2025
2277
  function createElementChildren(type, children, nativeRenderer, namespace) {
2026
2278
  return createChildChain(children, nativeRenderer, nativeRenderer.getNameSpace(type, namespace));
@@ -2030,10 +2282,7 @@ function createElement(nativeRenderer, atom, parentComponent, context) {
2030
2282
  const nativeNode = nativeRenderer.createElement(jsxNode.type, namespace);
2031
2283
  const props = jsxNode.props;
2032
2284
  let bindingRefs;
2033
- const propKeys = Object.keys(props);
2034
- const propKeyLen = propKeys.length;
2035
- for (let i = 0; i < propKeyLen; i++) {
2036
- const key = propKeys[i];
2285
+ for (const key in props) {
2037
2286
  if (key === "children") {
2038
2287
  atom.child = createElementChildren(jsxNode.type, props.children, nativeRenderer, namespace);
2039
2288
  continue;
@@ -2063,10 +2312,10 @@ function createElement(nativeRenderer, atom, parentComponent, context) {
2063
2312
  insertNode(nativeRenderer, atom, context);
2064
2313
  buildElementChildren(atom, nativeRenderer, parentComponent, {
2065
2314
  isParent: true,
2066
- host: nativeNode,
2067
- rootHost: context.rootHost
2315
+ container: nativeNode,
2316
+ rootContainer: context.rootContainer
2068
2317
  });
2069
- context.host = nativeNode;
2318
+ context.container = nativeNode;
2070
2319
  context.isParent = false;
2071
2320
  if (bindingRefs) {
2072
2321
  const refEffects = /* @__PURE__ */ new Map();
@@ -2078,7 +2327,7 @@ function createTextNode(nativeRenderer, atom, context) {
2078
2327
  const nativeNode = nativeRenderer.createTextNode(atom.jsxNode, atom.namespace);
2079
2328
  atom.nativeNode = nativeNode;
2080
2329
  insertNode(nativeRenderer, atom, context);
2081
- context.host = nativeNode;
2330
+ context.container = nativeNode;
2082
2331
  context.isParent = false;
2083
2332
  }
2084
2333
  function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComponent, context) {
@@ -2094,17 +2343,6 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
2094
2343
  let unBindRefs;
2095
2344
  let bindRefs;
2096
2345
  let updatedChildren = false;
2097
- const styleCache = /* @__PURE__ */ new WeakMap();
2098
- const toStyleObject = (style) => {
2099
- if (style && typeof style === "object") {
2100
- const cached = styleCache.get(style);
2101
- if (cached) return cached;
2102
- const normalized = styleToObject(style);
2103
- styleCache.set(style, normalized);
2104
- return normalized;
2105
- }
2106
- return styleToObject(style);
2107
- };
2108
2346
  comparePropsWithCallbacks(oldVNode.props, newVNode.props, (key, oldValue) => {
2109
2347
  if (key === "children") {
2110
2348
  updatedChildren = true;
@@ -2116,12 +2354,7 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
2116
2354
  return;
2117
2355
  }
2118
2356
  if (key === "style") {
2119
- const oldStyle = toStyleObject(oldValue);
2120
- const styleNames = Object.keys(oldStyle);
2121
- for (let i = 0; i < styleNames.length; i++) {
2122
- const styleName = styleNames[i];
2123
- nativeRenderer.removeStyle(nativeNode, styleName, isSvg);
2124
- }
2357
+ for (const styleName in styleToObject(oldValue)) nativeRenderer.removeStyle(nativeNode, styleName, isSvg);
2125
2358
  return;
2126
2359
  }
2127
2360
  if (listenerReg.test(key)) {
@@ -2145,12 +2378,8 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
2145
2378
  return;
2146
2379
  }
2147
2380
  if (key === "style") {
2148
- const styleObj = toStyleObject(value);
2149
- const styleNames = Object.keys(styleObj);
2150
- for (let i = 0; i < styleNames.length; i++) {
2151
- const styleName = styleNames[i];
2152
- nativeRenderer.setStyle(nativeNode, styleName, styleObj[styleName], isSvg);
2153
- }
2381
+ const styleObj = styleToObject(value);
2382
+ for (const styleName in styleObj) nativeRenderer.setStyle(nativeNode, styleName, styleObj[styleName], isSvg);
2154
2383
  return;
2155
2384
  }
2156
2385
  if (listenerReg.test(key)) {
@@ -2178,7 +2407,7 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
2178
2407
  return;
2179
2408
  }
2180
2409
  if (key === "style") {
2181
- comparePropsWithCallbacks(toStyleObject(oldValue), toStyleObject(newValue), (styleName) => {
2410
+ comparePropsWithCallbacks(styleToObject(oldValue), styleToObject(newValue), (styleName) => {
2182
2411
  nativeRenderer.removeStyle(nativeNode, styleName, isSvg);
2183
2412
  }, (styleName, styleValue) => {
2184
2413
  nativeRenderer.setStyle(nativeNode, styleName, styleValue, isSvg);
@@ -2237,7 +2466,7 @@ function viewfly(config) {
2237
2466
  const { context, nativeRenderer, autoUpdate, root } = Object.assign({ autoUpdate: true }, config);
2238
2467
  const modules = [];
2239
2468
  let destroyed = false;
2240
- let appHost = null;
2469
+ let appContainer = null;
2241
2470
  const rootProviders = [];
2242
2471
  const rootComponent = new RootComponent(() => {
2243
2472
  const rootContext = createContext(rootProviders, null, context);
@@ -2247,7 +2476,7 @@ function viewfly(config) {
2247
2476
  }, function() {
2248
2477
  if (destroyed || !autoUpdate) return;
2249
2478
  nextTick(() => {
2250
- render(appHost);
2479
+ render(appContainer);
2251
2480
  });
2252
2481
  });
2253
2482
  const render = createRenderer(rootComponent, nativeRenderer, config.elementNamespace);
@@ -2271,18 +2500,22 @@ function viewfly(config) {
2271
2500
  else modules.push(module);
2272
2501
  return app;
2273
2502
  },
2274
- mount(host) {
2503
+ mount(container) {
2275
2504
  if (isStarted) throw viewflyErrorFn("application has already started.");
2276
2505
  for (const module of modules) module.setup?.(app);
2277
2506
  isStarted = true;
2278
- appHost = host;
2279
- render(host);
2507
+ appContainer = container;
2508
+ render(container);
2280
2509
  for (const module of modules) module.onAfterStartup?.(app);
2281
2510
  if (!autoUpdate) return app;
2282
2511
  return app;
2283
2512
  },
2284
2513
  render() {
2285
- if (appHost) render(appHost);
2514
+ if (appContainer) {
2515
+ flushReactiveEffectsSync();
2516
+ render(appContainer);
2517
+ flushReactiveEffectsSync();
2518
+ }
2286
2519
  return app;
2287
2520
  },
2288
2521
  destroy() {
@@ -2303,13 +2536,31 @@ function viewfly(config) {
2303
2536
  * @returns 一个对象,对象的 value 属性是计算的值
2304
2537
  */
2305
2538
  function computed(getter) {
2306
- const proxy = new Proxy({ value: null }, readonlyProxyHandler);
2307
- watchEffect(() => {
2308
- internalWrite(() => {
2309
- proxy.value = getter();
2310
- });
2539
+ let cacheValue;
2540
+ let dirty = true;
2541
+ const target = { get value() {
2542
+ if (dirty) {
2543
+ dep.destroy();
2544
+ pushDepContext(dep);
2545
+ try {
2546
+ cacheValue = getter();
2547
+ dirty = false;
2548
+ } finally {
2549
+ popDepContext();
2550
+ }
2551
+ }
2552
+ return cacheValue;
2553
+ } };
2554
+ const dep = new Dep(() => {
2555
+ if (!dirty) {
2556
+ dirty = true;
2557
+ trigger(target, TriggerOpTypes.Set, "value");
2558
+ }
2559
+ }, "sync");
2560
+ registryComponentDestroyCallback(() => {
2561
+ dep.destroy();
2311
2562
  });
2312
- return proxy;
2563
+ return new Proxy(target, readonlyProxyHandler);
2313
2564
  }
2314
2565
  //#endregion
2315
2566
  //#region src/reactive/shallow-reactive.ts
@@ -2331,7 +2582,7 @@ var defaultShallowSetReactiveHandler = new SetReactiveHandler({
2331
2582
  });
2332
2583
  function shallowReactive(raw) {
2333
2584
  if (isReactive(raw)) return raw;
2334
- let proxy = rawToProxyCache.get(raw);
2585
+ let proxy = shallowRawToProxyCache.get(raw);
2335
2586
  if (proxy) return proxy;
2336
2587
  switch (getStringType(raw)) {
2337
2588
  case "[object Object]":
@@ -2350,8 +2601,8 @@ function shallowReactive(raw) {
2350
2601
  break;
2351
2602
  default: return raw;
2352
2603
  }
2353
- rawToProxyCache.set(raw, proxy);
2354
- proxyToRawCache.set(proxy, raw);
2604
+ shallowRawToProxyCache.set(raw, proxy);
2605
+ shallowProxyToRawCache.set(proxy, raw);
2355
2606
  return proxy;
2356
2607
  }
2357
2608
  //#endregion
@@ -2390,4 +2641,4 @@ function createSignal(state) {
2390
2641
  return signal;
2391
2642
  }
2392
2643
  //#endregion
2393
- export { ArrayReactiveHandler, Component, Dep, ForwardRef, Fragment, Inject, InjectFlags, Injectable, InjectionToken, Injector, JSXNodeFactory, MapReactiveHandler, NativeRenderer, NullInjector, ObjectReactiveHandler, Optional, Portal, Prop, ReflectiveInjector, RootComponent, Scope, Self, SetReactiveHandler, SkipSelf, THROW_IF_NOT_FOUND, TrackOpTypes, TriggerOpTypes, Type, applyMark, applyRefs, comparePropsWithCallbacks, computed, createContext, createContextProvider, createDynamicRef, createRef, createRenderer, createShallowReadonlyProxy, createSignal, defaultArrayReactiveHandler, defaultMapReactiveHandler, defaultObjectReactiveHandler, defaultSetReactiveHandler, defaultShallowArrayReactiveHandler, defaultShallowMapReactiveHandler, defaultShallowObjectReactiveHandler, defaultShallowSetReactiveHandler, forwardRef, getCurrentInstance, getDepContext, getSetupContext, inject, internalWrite, isReactive, jsx, jsxs, makeError, normalizeProvider, onMounted, onUnmounted, onUpdated, popDepContext, proxyToRawCache, pushDepContext, rawToProxyCache, reactive, readonlyProxyHandler, registryComponentDestroyCallback, shallowReactive, toRaw, track, trigger, updateRefs, viewfly, watch, watchEffect, withAnnotation, withMark };
2644
+ export { ArrayReactiveHandler, Component, Dep, ForwardRef, Fragment, Inject, InjectFlags, Injectable, InjectionToken, Injector, JSXNodeFactory, MapReactiveHandler, NativeRenderer, NullInjector, ObjectReactiveHandler, Optional, Portal, Prop, ReflectiveInjector, RootComponent, Scope, Self, SetReactiveHandler, SkipSelf, THROW_IF_NOT_FOUND, TrackOpTypes, TriggerOpTypes, Type, applyMark, applyRefs, comparePropsWithCallbacks, computed, createContext, createContextProvider, createDynamicRef, createRef, createRenderer, createShallowReadonlyProxy, createSignal, defaultArrayReactiveHandler, defaultMapReactiveHandler, defaultObjectReactiveHandler, defaultSetReactiveHandler, defaultShallowArrayReactiveHandler, defaultShallowMapReactiveHandler, defaultShallowObjectReactiveHandler, defaultShallowSetReactiveHandler, flushReactiveEffectsSync, forwardRef, getCurrentInstance, getDepContext, getSetupContext, inject, internalWrite, isReactive, jsx, jsxs, makeError, nextTick, normalizeProvider, onMounted, onUnmounted, onUpdated, popDepContext, proxyToRawCache, pushDepContext, rawToProxyCache, reactive, readonlyProxyHandler, registryComponentDestroyCallback, shallowProxyToRawCache, shallowRawToProxyCache, shallowReactive, toRaw, track, trigger, updateRefs, viewfly, watch, watchEffect, withAnnotation, withMark };