@viewfly/core 2.0.0-alpha.0 → 2.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.
@@ -601,110 +601,6 @@ class ReflectiveInjector {
601
601
 
602
602
  const Type = Function;
603
603
 
604
- const refKey = 'ref';
605
- function getObjectChanges(newProps, oldProps) {
606
- const changes = {
607
- remove: [],
608
- add: [],
609
- replace: []
610
- };
611
- for (const key in newProps) {
612
- const leftValue = newProps[key];
613
- const rightValue = oldProps[key];
614
- if (Reflect.has(oldProps, key)) {
615
- if (leftValue !== rightValue) {
616
- changes.replace.push([key, leftValue, rightValue]);
617
- }
618
- continue;
619
- }
620
- changes.add.push([key, leftValue]);
621
- }
622
- for (const key in oldProps) {
623
- if (!Reflect.has(newProps, key)) {
624
- changes.remove.push([key, oldProps[key]]);
625
- }
626
- }
627
- return changes;
628
- }
629
- function classToString(config) {
630
- if (typeof config === 'string') {
631
- return config;
632
- }
633
- if (!config) {
634
- return '';
635
- }
636
- if (Array.isArray(config)) {
637
- const classes = [];
638
- for (const i of config) {
639
- const v = classToString(i);
640
- if (v) {
641
- classes.push(v);
642
- }
643
- }
644
- return classes.join(' ');
645
- }
646
- if (typeof config === 'object') {
647
- if (config.toString !== Object.prototype.toString && !config.toString.toString().includes('[native code]')) {
648
- return config.toString();
649
- }
650
- const classes = [];
651
- for (const key in config) {
652
- if ({}.hasOwnProperty.call(config, key) && config[key]) {
653
- classes.push(key);
654
- }
655
- }
656
- return classes.join(' ');
657
- }
658
- return '';
659
- }
660
- function styleToObject(style) {
661
- if (typeof style !== 'string') {
662
- return style;
663
- }
664
- const obj = {};
665
- style.split(';').map(s => s.split(':')).forEach(v => {
666
- if (!v[0] || !v[1]) {
667
- return;
668
- }
669
- obj[v[0].trim()] = v[1].trim();
670
- });
671
- return obj;
672
- }
673
- const TextAtomType = Symbol('Text');
674
- const ElementAtomType = Symbol('Element');
675
- const ComponentAtomType = Symbol('Component');
676
-
677
- class Listener {
678
- constructor(effect) {
679
- Object.defineProperty(this, "effect", {
680
- enumerable: true,
681
- configurable: true,
682
- writable: true,
683
- value: effect
684
- });
685
- Object.defineProperty(this, "destroyCallbacks", {
686
- enumerable: true,
687
- configurable: true,
688
- writable: true,
689
- value: []
690
- });
691
- }
692
- destroy() {
693
- this.destroyCallbacks.forEach(fn => fn());
694
- this.destroyCallbacks = [];
695
- }
696
- }
697
- const listeners = [];
698
- function getCurrentListener() {
699
- return listeners.at(-1);
700
- }
701
- function pushListener(listener) {
702
- listeners.push(listener);
703
- }
704
- function popListener() {
705
- listeners.pop();
706
- }
707
-
708
604
  /**
709
605
  * 当组件第一次渲染完成时触发
710
606
  * @param callback
@@ -752,38 +648,6 @@ function onUpdated(callback) {
752
648
  }
753
649
  };
754
650
  }
755
- /**
756
- * 当组件 props 更新地调用
757
- * @param callback
758
- * @example
759
- * ```tsx
760
- * function YourComponent(props) {
761
- * onPropsChanged((currentProps, prevProps) => {
762
- * console.log(currentProps, prevProps)
763
- *
764
- * return () => {
765
- * console.log('destroy prev changed!')
766
- * }
767
- * })
768
- * return () => {
769
- * return <div>xxx</div>
770
- * }
771
- * }
772
- * ```
773
- */
774
- function onPropsChanged(callback) {
775
- const component = getSetupContext();
776
- if (!component.propsChangedCallbacks) {
777
- component.propsChangedCallbacks = [];
778
- }
779
- component.propsChangedCallbacks.push(callback);
780
- return () => {
781
- const index = component.propsChangedCallbacks.indexOf(callback);
782
- if (index > -1) {
783
- component.propsChangedCallbacks.splice(index, 1);
784
- }
785
- };
786
- }
787
651
  /**
788
652
  * 当组件销毁时调用回调函数
789
653
  * @param callback
@@ -894,135 +758,697 @@ function createRef() {
894
758
  return new StaticRef();
895
759
  }
896
760
 
897
- const componentSetupStack = [];
898
- const componentErrorFn = makeError('component');
899
- function getSetupContext(need = true) {
900
- const current = componentSetupStack[componentSetupStack.length - 1];
901
- if (!current && need) {
902
- // 防止因外部捕获异常引引起的缓存未清理的问题
903
- throw componentErrorFn('cannot be called outside the component!');
904
- }
905
- return current;
761
+ const toStr = Object.prototype.toString;
762
+ function getStringType(v) {
763
+ return toStr.call(v);
906
764
  }
907
- function toRefs(ref) {
908
- return (Array.isArray(ref) ? ref : [ref]).filter(i => {
909
- return i instanceof DynamicRef;
910
- });
765
+ function isArray(v) {
766
+ return Array.isArray(v);
911
767
  }
912
- /**
913
- * Viewfly 组件管理类,用于管理组件的生命周期,上下文等
914
- */
915
- class Component {
916
- get dirty() {
917
- return this._dirty;
918
- }
919
- get changed() {
920
- return this._changed;
921
- }
922
- constructor(parentComponent, type, props, key) {
923
- Object.defineProperty(this, "parentComponent", {
924
- enumerable: true,
925
- configurable: true,
926
- writable: true,
927
- value: parentComponent
928
- });
929
- Object.defineProperty(this, "type", {
930
- enumerable: true,
931
- configurable: true,
932
- writable: true,
933
- value: type
934
- });
935
- Object.defineProperty(this, "props", {
936
- enumerable: true,
937
- configurable: true,
938
- writable: true,
939
- value: props
940
- });
941
- Object.defineProperty(this, "key", {
942
- enumerable: true,
943
- configurable: true,
944
- writable: true,
945
- value: key
946
- });
947
- Object.defineProperty(this, "instance", {
948
- enumerable: true,
949
- configurable: true,
950
- writable: true,
951
- value: void 0
952
- });
953
- Object.defineProperty(this, "changedSubComponents", {
954
- enumerable: true,
955
- configurable: true,
956
- writable: true,
957
- value: new Set()
958
- });
959
- Object.defineProperty(this, "unmountedCallbacks", {
960
- enumerable: true,
961
- configurable: true,
962
- writable: true,
963
- value: void 0
964
- });
965
- Object.defineProperty(this, "mountCallbacks", {
966
- enumerable: true,
967
- configurable: true,
968
- writable: true,
969
- value: void 0
970
- });
971
- Object.defineProperty(this, "propsChangedCallbacks", {
768
+ const hasOwnProperty = Object.prototype.hasOwnProperty;
769
+ function hasOwn(target, key) {
770
+ return hasOwnProperty.call(target, key);
771
+ }
772
+
773
+ class Dep {
774
+ constructor(effect) {
775
+ Object.defineProperty(this, "effect", {
972
776
  enumerable: true,
973
777
  configurable: true,
974
778
  writable: true,
975
- value: void 0
779
+ value: effect
976
780
  });
977
- Object.defineProperty(this, "updatedCallbacks", {
781
+ Object.defineProperty(this, "destroyCallbacks", {
978
782
  enumerable: true,
979
783
  configurable: true,
980
784
  writable: true,
981
- value: void 0
785
+ value: []
982
786
  });
983
- Object.defineProperty(this, "updatedDestroyCallbacks", {
787
+ }
788
+ destroy() {
789
+ this.destroyCallbacks.forEach(callback => callback());
790
+ this.destroyCallbacks = [];
791
+ }
792
+ }
793
+ const deps = [];
794
+ function getDepContext() {
795
+ return deps.at(-1);
796
+ }
797
+ function pushDepContext(dep) {
798
+ deps.push(dep);
799
+ }
800
+ function popDepContext() {
801
+ deps.pop();
802
+ }
803
+ const subscribers = new WeakMap();
804
+ function getSubscriber(target) {
805
+ let subscriber = subscribers.get(target);
806
+ if (!subscriber) {
807
+ subscriber = new Map();
808
+ subscribers.set(target, subscriber);
809
+ }
810
+ return subscriber;
811
+ }
812
+ var TrackOpTypes;
813
+ (function (TrackOpTypes) {
814
+ TrackOpTypes["Get"] = "Get";
815
+ TrackOpTypes["Has"] = "Has";
816
+ TrackOpTypes["Iterate"] = "Iterate";
817
+ })(TrackOpTypes || (TrackOpTypes = {}));
818
+ var TriggerOpTypes;
819
+ (function (TriggerOpTypes) {
820
+ TriggerOpTypes["Set"] = "Set";
821
+ TriggerOpTypes["Add"] = "Add";
822
+ TriggerOpTypes["Delete"] = "Delete";
823
+ TriggerOpTypes["Clear"] = "Clear";
824
+ })(TriggerOpTypes || (TriggerOpTypes = {}));
825
+ const unKnownKey = Symbol('unKnownKey');
826
+ function track(target, type, key = unKnownKey) {
827
+ const dep = getDepContext();
828
+ if (dep) {
829
+ const subscriber = getSubscriber(target);
830
+ let record = subscriber.get(type);
831
+ if (!record) {
832
+ record = new Map();
833
+ subscriber.set(type, record);
834
+ }
835
+ let effects = record.get(key);
836
+ if (!effects) {
837
+ effects = new Set([dep]);
838
+ record.set(key, effects);
839
+ dep.destroyCallbacks.push(() => {
840
+ effects.delete(dep);
841
+ });
842
+ }
843
+ else if (!effects.has(dep)) {
844
+ dep.destroyCallbacks.push(() => {
845
+ effects.delete(dep);
846
+ });
847
+ effects.add(dep);
848
+ }
849
+ }
850
+ }
851
+ function runEffect(key, record) {
852
+ if (!record) {
853
+ return;
854
+ }
855
+ const effects = record.get(key);
856
+ if (effects) {
857
+ const fns = [...effects];
858
+ fns.forEach(i => i.effect());
859
+ }
860
+ }
861
+ function trigger(target, type, key = unKnownKey) {
862
+ const subscriber = getSubscriber(target);
863
+ if (subscriber) {
864
+ switch (type) {
865
+ case TriggerOpTypes.Set:
866
+ if (isArray(target)) {
867
+ const iterateRecord = subscriber.get(TrackOpTypes.Iterate);
868
+ runEffect(unKnownKey, iterateRecord);
869
+ }
870
+ runEffect(key, subscriber.get(TrackOpTypes.Get));
871
+ runEffect(key, subscriber.get(TrackOpTypes.Has));
872
+ break;
873
+ case TriggerOpTypes.Add:
874
+ case TriggerOpTypes.Clear:
875
+ case TriggerOpTypes.Delete:
876
+ {
877
+ const iterateRecord = subscriber.get(TrackOpTypes.Iterate);
878
+ runEffect(unKnownKey, iterateRecord);
879
+ runEffect(key, subscriber.get(TrackOpTypes.Has));
880
+ runEffect(key, subscriber.get(TrackOpTypes.Get));
881
+ }
882
+ break;
883
+ }
884
+ }
885
+ }
886
+ function registryComponentDestroyCallback(fn) {
887
+ const component = getSetupContext(false);
888
+ if (component) {
889
+ if (!component.unmountedCallbacks) {
890
+ component.unmountedCallbacks = [];
891
+ }
892
+ component.unmountedCallbacks.push(fn);
893
+ }
894
+ }
895
+
896
+ function createIterableIterator(wrapper) {
897
+ return {
898
+ *entries() {
899
+ const target = toRaw(this);
900
+ track(target, TrackOpTypes.Iterate);
901
+ for (const [key, value] of target.entries()) {
902
+ yield [wrapper(key), wrapper(value)];
903
+ }
904
+ },
905
+ *keys() {
906
+ const target = toRaw(this);
907
+ track(target, TrackOpTypes.Iterate);
908
+ for (const item of target.keys()) {
909
+ yield wrapper(item);
910
+ }
911
+ },
912
+ *values() {
913
+ const target = toRaw(this);
914
+ track(target, TrackOpTypes.Iterate);
915
+ for (const item of target.values()) {
916
+ yield wrapper(item);
917
+ }
918
+ }
919
+ };
920
+ }
921
+
922
+ function applyPredicateMethod(self, methodName, predicate, wrapper, thisArg) {
923
+ const target = toRaw(self);
924
+ track(target, TrackOpTypes.Iterate);
925
+ return target[methodName]((value, index, array) => {
926
+ return predicate.call(target, wrapper(value), index, array);
927
+ }, thisArg);
928
+ }
929
+ function applySearchMethod(self, methodName, args) {
930
+ const target = toRaw(self);
931
+ track(target, TrackOpTypes.Iterate);
932
+ return target[methodName](...args.map(toRaw));
933
+ }
934
+ function createArrayHandlers(wrapper) {
935
+ return Object.assign({ concat(...items) {
936
+ const target = toRaw(this);
937
+ trigger(target, TriggerOpTypes.Add);
938
+ return target.concat(...items);
939
+ },
940
+ every(predicate, thisArg) {
941
+ return applyPredicateMethod(this, 'every', predicate, wrapper, thisArg);
942
+ },
943
+ filter(predicate, thisArg) {
944
+ return applyPredicateMethod(this, 'filter', predicate, wrapper, thisArg);
945
+ },
946
+ find(predicate, thisArg) {
947
+ return applyPredicateMethod(this, 'find', predicate, wrapper, thisArg);
948
+ },
949
+ findIndex(predicate, thisArg) {
950
+ return applyPredicateMethod(this, 'findIndex', predicate, wrapper, thisArg);
951
+ },
952
+ findLast(predicate, thisArg) {
953
+ return applyPredicateMethod(this, 'findLast', predicate, wrapper, thisArg);
954
+ },
955
+ findLastIndex(predicate, thisArg) {
956
+ return applyPredicateMethod(this, 'findLastIndex', predicate, wrapper, thisArg);
957
+ },
958
+ forEach(callbackfn, thisArg) {
959
+ return applyPredicateMethod(this, 'forEach', callbackfn, wrapper, thisArg);
960
+ },
961
+ includes(...args) {
962
+ return applySearchMethod(this, 'includes', args);
963
+ },
964
+ indexOf(...args) {
965
+ return applySearchMethod(this, 'indexOf', args);
966
+ },
967
+ join(separator) {
968
+ const target = toRaw(this);
969
+ track(target, TrackOpTypes.Iterate);
970
+ return target.join(separator);
971
+ },
972
+ lastIndexOf(...args) {
973
+ return applySearchMethod(this, 'lastIndexOf', args);
974
+ },
975
+ map(callbackFn, thisArg) {
976
+ return applyPredicateMethod(this, 'map', callbackFn, wrapper, thisArg);
977
+ },
978
+ pop() {
979
+ const target = toRaw(this);
980
+ trigger(target, TriggerOpTypes.Delete);
981
+ return target.pop();
982
+ },
983
+ push(...items) {
984
+ const target = toRaw(this);
985
+ trigger(target, TriggerOpTypes.Add);
986
+ return target.push(...items);
987
+ },
988
+ reduce(callbackFn, ...args) {
989
+ const target = toRaw(this);
990
+ track(target, TrackOpTypes.Iterate);
991
+ return target.reduce((p, c, i, a) => {
992
+ if (args.length > 0) {
993
+ return callbackFn(p, wrapper(c), i, a);
994
+ }
995
+ return callbackFn(wrapper(p), wrapper(c), i, a);
996
+ }, ...args);
997
+ },
998
+ reduceRight(callbackFn, ...args) {
999
+ const target = toRaw(this);
1000
+ track(target, TrackOpTypes.Iterate);
1001
+ return target.reduceRight((p, c, i, a) => {
1002
+ if (args.length > 0) {
1003
+ return callbackFn(p, wrapper(c), i, a);
1004
+ }
1005
+ return callbackFn(wrapper(p), wrapper(c), i, a);
1006
+ }, ...args);
1007
+ },
1008
+ shift() {
1009
+ const target = toRaw(this);
1010
+ trigger(target, TriggerOpTypes.Delete);
1011
+ return target.shift();
1012
+ },
1013
+ some(predicate, thisArg) {
1014
+ return applyPredicateMethod(this, 'some', predicate, thisArg);
1015
+ },
1016
+ splice(start, deleteCount) {
1017
+ const target = toRaw(this);
1018
+ trigger(target, TriggerOpTypes.Set);
1019
+ trigger(target, TriggerOpTypes.Add);
1020
+ trigger(target, TriggerOpTypes.Delete);
1021
+ return target.splice(start, deleteCount).map(i => wrapper(i));
1022
+ },
1023
+ toReversed() {
1024
+ const target = toRaw(this);
1025
+ track(target, TrackOpTypes.Iterate);
1026
+ return target.toReversed();
1027
+ },
1028
+ toSorted(compareFn) {
1029
+ const target = toRaw(this);
1030
+ track(target, TrackOpTypes.Iterate);
1031
+ return target.toSorted(compareFn);
1032
+ },
1033
+ toSpliced(start, deleteCount, ...items) {
1034
+ const target = toRaw(this);
1035
+ track(target, TrackOpTypes.Iterate);
1036
+ return target.toSpliced(start, deleteCount, ...items);
1037
+ },
1038
+ unshift(...items) {
1039
+ const target = toRaw(this);
1040
+ trigger(target, TriggerOpTypes.Add);
1041
+ return target.unshift(...items);
1042
+ },
1043
+ [Symbol.iterator]() {
1044
+ return this.values();
1045
+ } }, createIterableIterator(wrapper));
1046
+ }
1047
+
1048
+ function createMapHandlers(wrapper) {
1049
+ return Object.assign({ get(key) {
1050
+ const target = toRaw(this);
1051
+ track(target, TrackOpTypes.Get, key);
1052
+ return wrapper(target.get(key));
1053
+ },
1054
+ set(key, value) {
1055
+ const target = toRaw(this);
1056
+ key = toRaw(key);
1057
+ value = toRaw(value);
1058
+ const has = target.has(key);
1059
+ const r = target.set(key, value);
1060
+ trigger(target, has ? TriggerOpTypes.Set : TriggerOpTypes.Add, key);
1061
+ return r;
1062
+ },
1063
+ has(key) {
1064
+ const target = toRaw(this);
1065
+ key = toRaw(key);
1066
+ track(target, TrackOpTypes.Has, key);
1067
+ return target.has(key);
1068
+ },
1069
+ delete(key) {
1070
+ const target = toRaw(this);
1071
+ key = toRaw(key);
1072
+ const r = target.delete(key);
1073
+ trigger(target, TriggerOpTypes.Delete, key);
1074
+ return r;
1075
+ },
1076
+ forEach(callbackFn, thisArg) {
1077
+ const target = toRaw(this);
1078
+ track(target, TrackOpTypes.Iterate, undefined);
1079
+ target.forEach((v, k, m) => {
1080
+ callbackFn.call(this, wrapper(v), wrapper(k), m);
1081
+ }, thisArg);
1082
+ },
1083
+ clear() {
1084
+ const target = toRaw(this);
1085
+ target.clear();
1086
+ trigger(target, TriggerOpTypes.Clear, undefined);
1087
+ },
1088
+ [Symbol.iterator]() {
1089
+ return this.entries();
1090
+ } }, createIterableIterator(wrapper));
1091
+ }
1092
+
1093
+ function createSetHandlers(wrapper) {
1094
+ return Object.assign({ add(value) {
1095
+ const target = toRaw(this);
1096
+ value = toRaw(value);
1097
+ if (!target.has(value)) {
1098
+ target.add(value);
1099
+ trigger(target, TriggerOpTypes.Add, undefined);
1100
+ }
1101
+ return this;
1102
+ },
1103
+ delete(value) {
1104
+ const target = toRaw(this);
1105
+ value = toRaw(value);
1106
+ const has = target.has(value);
1107
+ const b = target.delete(value);
1108
+ if (!has) {
1109
+ trigger(target, TriggerOpTypes.Delete, undefined);
1110
+ }
1111
+ return b;
1112
+ },
1113
+ has(key) {
1114
+ const target = toRaw(this);
1115
+ key = toRaw(key);
1116
+ track(target, TrackOpTypes.Has, key);
1117
+ return target.has(key);
1118
+ },
1119
+ forEach(callbackFn, thisArg) {
1120
+ const target = toRaw(this);
1121
+ track(target, TrackOpTypes.Iterate, undefined);
1122
+ target.forEach((v, k, m) => {
1123
+ callbackFn.call(this, wrapper(v), wrapper(k), m);
1124
+ }, thisArg);
1125
+ },
1126
+ clear() {
1127
+ const target = toRaw(this);
1128
+ const size = target.size;
1129
+ if (size !== 0) {
1130
+ target.clear();
1131
+ trigger(target, TriggerOpTypes.Clear, undefined);
1132
+ }
1133
+ },
1134
+ [Symbol.iterator]() {
1135
+ return this.values();
1136
+ } }, createIterableIterator(wrapper));
1137
+ }
1138
+
1139
+ const reactiveErrorFn = makeError('reactive');
1140
+ const rawToProxyCache = new WeakMap();
1141
+ const proxyToRawCache = new WeakMap();
1142
+ function toRaw(value) {
1143
+ if (proxyToRawCache.has(value)) {
1144
+ return proxyToRawCache.get(value);
1145
+ }
1146
+ return value;
1147
+ }
1148
+ function isReactive(value) {
1149
+ return proxyToRawCache.has(value);
1150
+ }
1151
+ let fromInternalWrite = false;
1152
+ function internalWrite(fn) {
1153
+ fromInternalWrite = true;
1154
+ fn();
1155
+ fromInternalWrite = false;
1156
+ }
1157
+ class ObjectReactiveHandler {
1158
+ constructor(config) {
1159
+ Object.defineProperty(this, "isShallow", {
984
1160
  enumerable: true,
985
1161
  configurable: true,
986
1162
  writable: true,
987
1163
  value: void 0
988
1164
  });
989
- Object.defineProperty(this, "propsChangedDestroyCallbacks", {
1165
+ Object.defineProperty(this, "isReadonly", {
990
1166
  enumerable: true,
991
1167
  configurable: true,
992
1168
  writable: true,
993
1169
  value: void 0
994
1170
  });
995
- Object.defineProperty(this, "_dirty", {
996
- enumerable: true,
997
- configurable: true,
998
- writable: true,
999
- value: true
1000
- });
1001
- Object.defineProperty(this, "_changed", {
1171
+ this.isReadonly = config.readonly;
1172
+ this.isShallow = config.shallow;
1173
+ }
1174
+ set(target, p, newValue, receiver) {
1175
+ if (this.isReadonly && !fromInternalWrite) {
1176
+ throw reactiveErrorFn('Object is readonly!');
1177
+ }
1178
+ newValue = toRaw(newValue);
1179
+ const oldValue = target[p];
1180
+ if (oldValue === newValue) {
1181
+ return Reflect.set(target, p, newValue, receiver);
1182
+ }
1183
+ const b = Reflect.set(target, p, newValue, receiver);
1184
+ fromInternalWrite = false;
1185
+ if (hasOwn(target, p)) {
1186
+ trigger(target, TriggerOpTypes.Set, p);
1187
+ }
1188
+ else {
1189
+ trigger(target, TriggerOpTypes.Add, p);
1190
+ }
1191
+ return b;
1192
+ }
1193
+ get(target, p, receiver) {
1194
+ track(target, TrackOpTypes.Get, p);
1195
+ const value = Reflect.get(target, p, receiver);
1196
+ if (this.isShallow) {
1197
+ return value;
1198
+ }
1199
+ return reactive(value);
1200
+ }
1201
+ deleteProperty(target, p) {
1202
+ const b = Reflect.deleteProperty(target, p);
1203
+ trigger(target, TriggerOpTypes.Delete, p);
1204
+ return b;
1205
+ }
1206
+ ownKeys(target) {
1207
+ track(target, TrackOpTypes.Iterate);
1208
+ return Reflect.ownKeys(target);
1209
+ }
1210
+ }
1211
+ function noReactive(v) {
1212
+ return v;
1213
+ }
1214
+ class ArrayReactiveHandler extends ObjectReactiveHandler {
1215
+ constructor(config) {
1216
+ super(config);
1217
+ Object.defineProperty(this, "interceptors", {
1002
1218
  enumerable: true,
1003
1219
  configurable: true,
1004
1220
  writable: true,
1005
- value: true
1221
+ value: createArrayHandlers(this.isShallow ? noReactive : reactive)
1006
1222
  });
1007
- Object.defineProperty(this, "isFirstRendering", {
1223
+ }
1224
+ get(target, p, receiver) {
1225
+ if (Reflect.has(this.interceptors, p) && p in target) {
1226
+ return this.interceptors[p];
1227
+ }
1228
+ return super.get(target, p, receiver);
1229
+ }
1230
+ }
1231
+ class MapReactiveHandler extends ObjectReactiveHandler {
1232
+ constructor(config) {
1233
+ super(config);
1234
+ Object.defineProperty(this, "interceptors", {
1008
1235
  enumerable: true,
1009
1236
  configurable: true,
1010
1237
  writable: true,
1011
- value: true
1238
+ value: createMapHandlers(this.isShallow ? noReactive : reactive)
1012
1239
  });
1013
- Object.defineProperty(this, "refs", {
1240
+ }
1241
+ get(target, p, receiver) {
1242
+ if (Reflect.has(this.interceptors, p) && p in target) {
1243
+ return this.interceptors[p];
1244
+ }
1245
+ if (p === 'size') {
1246
+ track(target, TrackOpTypes.Iterate, p);
1247
+ return Reflect.get(target, p);
1248
+ }
1249
+ return super.get(target, p, receiver);
1250
+ }
1251
+ }
1252
+ class SetReactiveHandler extends ObjectReactiveHandler {
1253
+ constructor(config) {
1254
+ super(config);
1255
+ Object.defineProperty(this, "interceptors", {
1014
1256
  enumerable: true,
1015
1257
  configurable: true,
1016
1258
  writable: true,
1017
- value: null
1259
+ value: createSetHandlers(this.isShallow ? noReactive : reactive)
1018
1260
  });
1019
- Object.defineProperty(this, "listener", {
1020
- enumerable: true,
1021
- configurable: true,
1022
- writable: true,
1023
- value: new Listener(() => {
1024
- this.markAsDirtied();
1025
- })
1261
+ }
1262
+ get(target, p, receiver) {
1263
+ if (Reflect.has(this.interceptors, p) && p in target) {
1264
+ return this.interceptors[p];
1265
+ }
1266
+ if (p === 'size') {
1267
+ track(target, TrackOpTypes.Iterate, p);
1268
+ return Reflect.get(target, p);
1269
+ }
1270
+ return super.get(target, p, receiver);
1271
+ }
1272
+ }
1273
+ const defaultObjectReactiveHandler = new ObjectReactiveHandler({
1274
+ readonly: false,
1275
+ shallow: false
1276
+ });
1277
+ const defaultArrayReactiveHandler = new ArrayReactiveHandler({
1278
+ readonly: false,
1279
+ shallow: false
1280
+ });
1281
+ const defaultMapReactiveHandler = new MapReactiveHandler({
1282
+ readonly: false,
1283
+ shallow: false
1284
+ });
1285
+ const defaultSetReactiveHandler = new SetReactiveHandler({
1286
+ readonly: false,
1287
+ shallow: false
1288
+ });
1289
+ const readonlyProxyHandler = new ObjectReactiveHandler({
1290
+ shallow: true,
1291
+ readonly: true
1292
+ });
1293
+ function reactive(raw) {
1294
+ if (isReactive(raw)) {
1295
+ return raw;
1296
+ }
1297
+ let proxy = rawToProxyCache.get(raw);
1298
+ if (proxy) {
1299
+ return proxy;
1300
+ }
1301
+ const type = getStringType(raw);
1302
+ switch (type) {
1303
+ case '[object Object]':
1304
+ proxy = new Proxy(raw, defaultObjectReactiveHandler);
1305
+ break;
1306
+ case '[object Array]':
1307
+ proxy = new Proxy(raw, defaultArrayReactiveHandler);
1308
+ break;
1309
+ case '[object Set]':
1310
+ case '[object WeakSet]':
1311
+ proxy = new Proxy(raw, defaultSetReactiveHandler);
1312
+ break;
1313
+ case '[object Map]':
1314
+ case '[object WeakMap]':
1315
+ proxy = new Proxy(raw, defaultMapReactiveHandler);
1316
+ break;
1317
+ default:
1318
+ return raw;
1319
+ }
1320
+ rawToProxyCache.set(raw, proxy);
1321
+ proxyToRawCache.set(proxy, raw);
1322
+ return proxy;
1323
+ }
1324
+
1325
+ function hasChange(newProps, oldProps) {
1326
+ const newKeys = Object.keys(oldProps);
1327
+ const oldKeys = Object.keys(newProps);
1328
+ if (oldKeys.length !== newKeys.length) {
1329
+ return true;
1330
+ }
1331
+ const len = oldKeys.length;
1332
+ for (let i = 0; i < len; i++) {
1333
+ const key = newKeys[i];
1334
+ if (newProps[key] !== oldProps[key]) {
1335
+ return true;
1336
+ }
1337
+ }
1338
+ return false;
1339
+ }
1340
+ const refKey = 'ref';
1341
+ function comparePropsWithCallbacks(oldProps, newProps, onDeleted, onAdded, onUpdated) {
1342
+ for (const key in oldProps) {
1343
+ if (!(key in newProps)) {
1344
+ onDeleted(key, oldProps[key]);
1345
+ }
1346
+ }
1347
+ for (const key in newProps) {
1348
+ if (!(key in oldProps)) {
1349
+ onAdded(key, newProps[key]);
1350
+ }
1351
+ else if (oldProps[key] !== newProps[key]) {
1352
+ onUpdated(key, newProps[key], oldProps[key]);
1353
+ }
1354
+ }
1355
+ }
1356
+ function classToString(config) {
1357
+ if (typeof config === 'string') {
1358
+ return config;
1359
+ }
1360
+ if (!config) {
1361
+ return '';
1362
+ }
1363
+ if (Array.isArray(config)) {
1364
+ const classes = [];
1365
+ for (const i of config) {
1366
+ const v = classToString(i);
1367
+ if (v) {
1368
+ classes.push(v);
1369
+ }
1370
+ }
1371
+ return classes.join(' ');
1372
+ }
1373
+ if (typeof config === 'object') {
1374
+ if (config.toString !== Object.prototype.toString && !config.toString.toString().includes('[native code]')) {
1375
+ return config.toString();
1376
+ }
1377
+ const classes = [];
1378
+ for (const key in config) {
1379
+ if ({}.hasOwnProperty.call(config, key) && config[key]) {
1380
+ classes.push(key);
1381
+ }
1382
+ }
1383
+ return classes.join(' ');
1384
+ }
1385
+ return '';
1386
+ }
1387
+ function styleToObject(style) {
1388
+ if (typeof style !== 'string') {
1389
+ return style || {};
1390
+ }
1391
+ const obj = {};
1392
+ style.split(';').map(s => s.split(':')).forEach(v => {
1393
+ if (!v[0] || !v[1]) {
1394
+ return;
1395
+ }
1396
+ obj[v[0].trim()] = v[1].trim();
1397
+ });
1398
+ return obj;
1399
+ }
1400
+ const TextAtomType = Symbol('Text');
1401
+ const ElementAtomType = Symbol('Element');
1402
+ const ComponentAtomType = Symbol('Component');
1403
+
1404
+ const componentSetupStack = [];
1405
+ const componentErrorFn = makeError('component');
1406
+ function getSetupContext(need = true) {
1407
+ const current = componentSetupStack[componentSetupStack.length - 1];
1408
+ if (!current && need) {
1409
+ // 防止因外部捕获异常引引起的缓存未清理的问题
1410
+ throw componentErrorFn('cannot be called outside the component!');
1411
+ }
1412
+ return current;
1413
+ }
1414
+ function toRefs(ref) {
1415
+ return (Array.isArray(ref) ? ref : [ref]).filter(i => {
1416
+ return i instanceof DynamicRef;
1417
+ });
1418
+ }
1419
+ function createReadonlyProxy(value) {
1420
+ return new Proxy(value, readonlyProxyHandler);
1421
+ }
1422
+ /**
1423
+ * Viewfly 组件管理类,用于管理组件的生命周期,上下文等
1424
+ */
1425
+ class Component {
1426
+ get dirty() {
1427
+ return this._dirty;
1428
+ }
1429
+ get changed() {
1430
+ return this._changed;
1431
+ }
1432
+ constructor(parentComponent, type, props, key) {
1433
+ this.parentComponent = parentComponent;
1434
+ this.type = type;
1435
+ this.props = props;
1436
+ this.key = key;
1437
+ this.instance = null;
1438
+ this.changedSubComponents = new Set();
1439
+ this.viewMetadata = null;
1440
+ this.unmountedCallbacks = null;
1441
+ this.mountCallbacks = null;
1442
+ this.updatedCallbacks = null;
1443
+ this.updatedDestroyCallbacks = null;
1444
+ this._dirty = true;
1445
+ this._changed = false;
1446
+ this.isFirstRendering = true;
1447
+ this.refs = null;
1448
+ this.rawProps = props;
1449
+ this.props = createReadonlyProxy(Object.assign({}, props));
1450
+ this.listener = new Dep(() => {
1451
+ this.markAsDirtied();
1026
1452
  });
1027
1453
  }
1028
1454
  markAsDirtied() {
@@ -1037,117 +1463,109 @@ class Component {
1037
1463
  return;
1038
1464
  }
1039
1465
  this._changed = true;
1040
- if (this.parentComponent instanceof Component) {
1466
+ if (this.parentComponent) {
1041
1467
  this.parentComponent.markAsChanged(this);
1042
1468
  }
1043
1469
  }
1044
1470
  render(update) {
1045
- const self = this;
1046
- const proxiesProps = new Proxy(this.props, {
1047
- get(_, key) {
1048
- // 必须用 self,因为 props 会随着页面更新变更,使用 self 才能更新引用
1049
- return self.props[key];
1050
- },
1051
- set() {
1052
- // 防止因外部捕获异常引引起的缓存未清理的问题
1053
- if (isSetup) {
1054
- componentSetupStack.pop();
1055
- }
1056
- throw componentErrorFn('component props is readonly!');
1057
- }
1058
- });
1059
1471
  componentSetupStack.push(this);
1060
- let isSetup = true;
1061
- const render = this.type(proxiesProps);
1472
+ const render = this.type(this.props);
1062
1473
  const isRenderFn = typeof render === 'function';
1063
1474
  this.instance = isRenderFn ? { $render: render } : render;
1064
1475
  const refs = toRefs(this.props.ref);
1065
1476
  if (refs.length) {
1066
1477
  this.refs = refs;
1067
1478
  onMounted(() => {
1068
- for (const ref of refs) {
1479
+ const refs = this.refs;
1480
+ const length = refs.length;
1481
+ for (let i = 0; i < length; i++) {
1482
+ const ref = refs[i];
1069
1483
  ref.bind(this.instance);
1070
1484
  }
1071
1485
  return () => {
1072
- for (const ref of refs) {
1486
+ const refs = this.refs;
1487
+ const length = refs.length;
1488
+ for (let i = 0; i < length; i++) {
1489
+ const ref = refs[i];
1073
1490
  ref.unBind(this.instance);
1074
1491
  }
1075
1492
  };
1076
1493
  });
1077
1494
  }
1078
- isSetup = false;
1079
1495
  componentSetupStack.pop();
1080
- pushListener(this.listener);
1496
+ pushDepContext(this.listener);
1081
1497
  const template = this.instance.$render();
1082
- popListener();
1498
+ popDepContext();
1083
1499
  update(template, this.instance.$portalHost);
1084
1500
  this.rendered();
1085
1501
  }
1086
- update(newProps, updateChildren, reuseChildren) {
1087
- const oldProps = this.props;
1088
- if (newProps !== oldProps) {
1089
- const { add, remove, replace } = getObjectChanges(newProps, oldProps);
1090
- if (add.length || remove.length || replace.length) {
1091
- this.invokePropsChangedHooks(newProps);
1092
- }
1093
- else if (!this.dirty) {
1094
- this.props = newProps;
1095
- reuseChildren(false);
1096
- this.rendered();
1097
- return;
1098
- }
1099
- const newRefs = toRefs(newProps.ref);
1100
- if (this.refs) {
1101
- for (const oldRef of this.refs) {
1102
- if (!newRefs.includes(oldRef)) {
1103
- oldRef.unBind(this.instance);
1104
- }
1502
+ updateProps(newProps) {
1503
+ const oldProps = this.rawProps;
1504
+ this.rawProps = newProps;
1505
+ const newRefs = toRefs(newProps.ref);
1506
+ comparePropsWithCallbacks(oldProps, newProps, key => {
1507
+ internalWrite(() => {
1508
+ Reflect.deleteProperty(oldProps, key);
1509
+ });
1510
+ }, (key, value) => {
1511
+ internalWrite(() => {
1512
+ this.props[key] = value;
1513
+ });
1514
+ }, (key, value) => {
1515
+ internalWrite(() => {
1516
+ this.props[key] = value;
1517
+ });
1518
+ });
1519
+ if (this.refs) {
1520
+ const len = this.refs.length;
1521
+ for (let i = 0; i < len; i++) {
1522
+ const oldRef = this.refs[i];
1523
+ if (!newRefs.includes(oldRef)) {
1524
+ oldRef.unBind(this.instance);
1105
1525
  }
1106
1526
  }
1107
- for (const newRef of newRefs) {
1108
- newRef.bind(this.instance);
1109
- }
1110
- if (newRefs.length) {
1111
- this.refs = newRefs;
1112
- }
1113
1527
  }
1528
+ const len = newRefs.length;
1529
+ for (let i = 0; i < len; i++) {
1530
+ const newRef = newRefs[i];
1531
+ newRef.bind(this.instance);
1532
+ }
1533
+ if (len) {
1534
+ this.refs = newRefs;
1535
+ }
1536
+ }
1537
+ canUpdate(oldProps, newProps) {
1114
1538
  if (typeof this.instance.$useMemo === 'function') {
1115
1539
  if (this.instance.$useMemo(newProps, oldProps)) {
1116
- reuseChildren(true);
1117
- this.rendered();
1118
- return;
1540
+ return false;
1119
1541
  }
1120
1542
  }
1543
+ return true;
1544
+ }
1545
+ rerender() {
1121
1546
  this.listener.destroy();
1122
- pushListener(this.listener);
1547
+ pushDepContext(this.listener);
1123
1548
  const template = this.instance.$render();
1124
- popListener();
1125
- updateChildren(template);
1126
- this.rendered();
1549
+ popDepContext();
1550
+ return template;
1127
1551
  }
1128
1552
  destroy() {
1129
- var _a, _b, _c;
1130
1553
  this.listener.destroy();
1131
- (_a = this.updatedDestroyCallbacks) === null || _a === void 0 ? void 0 : _a.forEach(fn => {
1132
- fn();
1133
- });
1134
- (_b = this.propsChangedDestroyCallbacks) === null || _b === void 0 ? void 0 : _b.forEach(fn => {
1135
- fn();
1136
- });
1137
- (_c = this.unmountedCallbacks) === null || _c === void 0 ? void 0 : _c.forEach(fn => {
1138
- fn();
1139
- });
1140
- if (this.parentComponent instanceof Component) {
1141
- this.parentComponent.changedSubComponents.delete(this);
1554
+ if (this.updatedDestroyCallbacks) {
1555
+ this.updatedDestroyCallbacks.forEach(fn => {
1556
+ fn();
1557
+ });
1558
+ }
1559
+ if (this.unmountedCallbacks) {
1560
+ this.unmountedCallbacks.forEach(fn => {
1561
+ fn();
1562
+ });
1142
1563
  }
1143
1564
  this.parentComponent =
1144
- this.propsChangedDestroyCallbacks =
1145
- this.updatedDestroyCallbacks =
1146
- this.mountCallbacks =
1147
- this.updatedCallbacks =
1148
- this.propsChangedCallbacks =
1149
- this.unmountedCallbacks = null;
1150
- this.changedSubComponents.clear();
1565
+ this.updatedDestroyCallbacks =
1566
+ this.mountCallbacks =
1567
+ this.updatedCallbacks =
1568
+ this.unmountedCallbacks = null;
1151
1569
  }
1152
1570
  rendered() {
1153
1571
  this.changedSubComponents.clear();
@@ -1160,35 +1578,18 @@ class Component {
1160
1578
  }
1161
1579
  if (this.changed) {
1162
1580
  Promise.resolve().then(() => {
1163
- if (this.parentComponent instanceof Component) {
1581
+ if (this.parentComponent) {
1164
1582
  this.parentComponent.markAsChanged(this);
1165
1583
  }
1166
1584
  });
1167
1585
  }
1168
1586
  }
1169
- invokePropsChangedHooks(newProps) {
1170
- const oldProps = this.props;
1171
- this.props = newProps;
1172
- if (this.propsChangedCallbacks) {
1173
- if (this.propsChangedDestroyCallbacks) {
1174
- this.propsChangedDestroyCallbacks.forEach(fn => {
1175
- fn();
1176
- });
1177
- }
1178
- const propsChangedDestroyCallbacks = [];
1179
- for (const fn of this.propsChangedCallbacks) {
1180
- const destroyFn = fn(newProps, oldProps);
1181
- if (typeof destroyFn === 'function') {
1182
- propsChangedDestroyCallbacks.push(destroyFn);
1183
- }
1184
- }
1185
- this.propsChangedDestroyCallbacks = propsChangedDestroyCallbacks.length ? propsChangedDestroyCallbacks : null;
1186
- }
1187
- }
1188
1587
  invokeMountHooks() {
1189
1588
  const unmountedCallbacks = [];
1190
1589
  if (this.mountCallbacks) {
1191
- for (const fn of this.mountCallbacks) {
1590
+ const len = this.mountCallbacks.length;
1591
+ for (let i = 0; i < len; ++i) {
1592
+ const fn = this.mountCallbacks[i];
1192
1593
  const destroyFn = fn();
1193
1594
  if (typeof destroyFn === 'function') {
1194
1595
  unmountedCallbacks.push(destroyFn);
@@ -1213,7 +1614,9 @@ class Component {
1213
1614
  });
1214
1615
  }
1215
1616
  const updatedDestroyCallbacks = [];
1216
- for (const fn of this.updatedCallbacks) {
1617
+ const len = this.updatedCallbacks.length;
1618
+ for (let i = 0; i < len; ++i) {
1619
+ const fn = this.updatedCallbacks[i];
1217
1620
  const destroyFn = fn();
1218
1621
  if (typeof destroyFn === 'function') {
1219
1622
  updatedDestroyCallbacks.push(destroyFn);
@@ -1231,8 +1634,7 @@ function getCurrentInstance() {
1231
1634
  }
1232
1635
 
1233
1636
  const injectMap = new WeakMap();
1234
- function getParentInjector(component) {
1235
- let start = component.parentComponent;
1637
+ function getInjector(start) {
1236
1638
  while (start) {
1237
1639
  const injector = injectMap.get(start);
1238
1640
  if (injector) {
@@ -1245,7 +1647,7 @@ function getParentInjector(component) {
1245
1647
  function createContext(providers, scope, parentInjector) {
1246
1648
  return function context(props) {
1247
1649
  const instance = getCurrentInstance();
1248
- const injector = new ReflectiveInjector(parentInjector || getParentInjector(instance), providers, scope);
1650
+ const injector = new ReflectiveInjector(parentInjector || getInjector(instance), providers, scope);
1249
1651
  injectMap.set(instance, injector);
1250
1652
  return () => {
1251
1653
  return props.children;
@@ -1257,9 +1659,42 @@ function createContext(providers, scope, parentInjector) {
1257
1659
  */
1258
1660
  function inject(token, notFoundValue = THROW_IF_NOT_FOUND, flags) {
1259
1661
  const component = getCurrentInstance();
1260
- const injector = getParentInjector(component);
1662
+ const injector = getInjector(component);
1261
1663
  return injector.get(token, notFoundValue, flags);
1262
1664
  }
1665
+ /**
1666
+ * 给组件添加注解
1667
+ * @param annotation
1668
+ * @param componentSetup
1669
+ * @example
1670
+ * ```ts
1671
+ * export customScope = new Scope('scopeName')
1672
+ * export const App = withAnnotation({
1673
+ * scope: customScope,
1674
+ * providers: [
1675
+ * ExampleService
1676
+ * ]
1677
+ * }, function(props: Props) {
1678
+ * return () => {
1679
+ * return <div>...</div>
1680
+ * }
1681
+ * })
1682
+ * ```
1683
+ */
1684
+ function withAnnotation(annotation, componentSetup) {
1685
+ return function (props) {
1686
+ const instance = getCurrentInstance();
1687
+ const parentInjector = injectMap.get(instance) || getInjector(instance.parentComponent);
1688
+ const injector = new ReflectiveInjector(parentInjector, [{
1689
+ provide: Injector,
1690
+ useFactory() {
1691
+ return injector;
1692
+ }
1693
+ }, ...(annotation.providers || [])], annotation.scope);
1694
+ injectMap.set(instance, injector);
1695
+ return componentSetup(props);
1696
+ };
1697
+ }
1263
1698
 
1264
1699
  class NativeRenderer {
1265
1700
  }
@@ -1294,7 +1729,6 @@ const ElementNamespaceMap = {
1294
1729
  svg: 'svg',
1295
1730
  math: 'mathml',
1296
1731
  };
1297
- const componentViewCache = new WeakMap();
1298
1732
  const listenerReg = /^on[A-Z]/;
1299
1733
  function createRenderer(component, nativeRenderer, namespace) {
1300
1734
  let isInit = true;
@@ -1318,7 +1752,7 @@ function createRenderer(component, nativeRenderer, namespace) {
1318
1752
  });
1319
1753
  }
1320
1754
  else {
1321
- updateView(nativeRenderer, component, false);
1755
+ deepUpdateByComponentDirtyTree(nativeRenderer, component, false);
1322
1756
  }
1323
1757
  };
1324
1758
  }
@@ -1343,37 +1777,39 @@ function buildElementChildren(atom, nativeRenderer, parentComponent, context) {
1343
1777
  child = child.sibling;
1344
1778
  }
1345
1779
  }
1346
- function updateView(nativeRenderer, component, needMove) {
1780
+ function patchComponent(nativeRenderer, component, oldChildAtom, newAtom, context, needMove) {
1781
+ const newTemplate = component.rerender();
1782
+ newAtom.child = createChildChain(newTemplate, newAtom.namespace);
1783
+ diff(nativeRenderer, component, newAtom.child, oldChildAtom, context, needMove);
1784
+ }
1785
+ function deepUpdateByComponentDirtyTree(nativeRenderer, component, needMove) {
1347
1786
  if (component.dirty) {
1348
- const { atom, host, isParent, rootHost } = componentViewCache.get(component);
1349
- applyChanges(nativeRenderer, component, atom, {
1350
- host,
1351
- isParent,
1352
- rootHost
1353
- }, needMove);
1787
+ const canUpdate = component.canUpdate(component.props, component.props);
1788
+ if (canUpdate) {
1789
+ const { atom, host, isParent, rootHost } = component.viewMetadata;
1790
+ const context = {
1791
+ host,
1792
+ isParent,
1793
+ rootHost
1794
+ };
1795
+ const diffAtom = atom.child;
1796
+ patchComponent(nativeRenderer, component, diffAtom, atom, context, needMove);
1797
+ const next = atom.sibling;
1798
+ if (next && next.jsxNode instanceof Component) {
1799
+ const view = next.jsxNode.viewMetadata;
1800
+ view.host = context.host;
1801
+ view.isParent = context.isParent;
1802
+ }
1803
+ }
1804
+ component.rendered();
1354
1805
  }
1355
1806
  else if (component.changed) {
1356
1807
  component.changedSubComponents.forEach(child => {
1357
- updateView(nativeRenderer, child, needMove);
1808
+ deepUpdateByComponentDirtyTree(nativeRenderer, child, needMove);
1358
1809
  });
1359
1810
  component.rendered();
1360
1811
  }
1361
1812
  }
1362
- function applyChanges(nativeRenderer, component, atom, context, needMove) {
1363
- const diffAtom = atom.child;
1364
- component.update(component.props, newTemplate => {
1365
- atom.child = createChildChain(newTemplate, atom.namespace);
1366
- diff(nativeRenderer, component, atom.child, diffAtom, context, needMove);
1367
- const next = atom.sibling;
1368
- if (next && next.jsxNode instanceof Component) {
1369
- const view = componentViewCache.get(next.jsxNode);
1370
- view.host = context.host;
1371
- view.isParent = context.isParent;
1372
- }
1373
- }, (skipSubComponentDiff) => {
1374
- reuseComponentView(nativeRenderer, atom, context, needMove, skipSubComponentDiff);
1375
- });
1376
- }
1377
1813
  function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, needMove) {
1378
1814
  const commits = [];
1379
1815
  function changeOffset() {
@@ -1389,7 +1825,8 @@ function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, needMo
1389
1825
  dirtyDiffAtom = dirtyDiffAtom.sibling;
1390
1826
  }
1391
1827
  let offset = 0;
1392
- for (let i = 0; i < commits.length; i++) {
1828
+ const len = commits.length;
1829
+ for (let i = 0; i < len; i++) {
1393
1830
  const commit = commits[i];
1394
1831
  while (oldAtom) {
1395
1832
  if (oldAtom.index <= i) {
@@ -1399,7 +1836,7 @@ function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, needMo
1399
1836
  }
1400
1837
  break;
1401
1838
  }
1402
- commit(offset, needMove);
1839
+ commit.callback(commit.params, offset, needMove);
1403
1840
  }
1404
1841
  }
1405
1842
  function createChanges(newAtom, oldAtom, nativeRenderer, commits, context, parentComponent, effect) {
@@ -1408,17 +1845,19 @@ function createChanges(newAtom, oldAtom, nativeRenderer, commits, context, paren
1408
1845
  while (oldAtom) {
1409
1846
  const newAtomType = newAtom.type;
1410
1847
  if (oldAtom.type === newAtomType && oldAtom.nodeType === newAtom.nodeType && oldAtom.key === newAtom.key) {
1411
- let commit;
1412
- if (newAtomType === TextAtomType) {
1413
- commit = updateText(newAtom, oldAtom, nativeRenderer, context);
1414
- }
1415
- else if (newAtomType === ComponentAtomType) {
1416
- commit = updateComponent(newAtom, oldAtom, nativeRenderer, context);
1417
- }
1418
- else {
1419
- commit = updateElement(newAtom, oldAtom, nativeRenderer, context, parentComponent);
1420
- }
1421
- commits.push(commit);
1848
+ commits.push({
1849
+ callback: newAtomType === TextAtomType ? updateText :
1850
+ newAtomType === ComponentAtomType ? updateComponent :
1851
+ updateElement,
1852
+ params: {
1853
+ oldAtom,
1854
+ newAtom,
1855
+ nativeRenderer,
1856
+ context,
1857
+ effect,
1858
+ parentComponent
1859
+ }
1860
+ });
1422
1861
  const next = oldAtom.sibling;
1423
1862
  if (!prev) {
1424
1863
  return next;
@@ -1429,81 +1868,84 @@ function createChanges(newAtom, oldAtom, nativeRenderer, commits, context, paren
1429
1868
  prev = oldAtom;
1430
1869
  oldAtom = oldAtom.sibling;
1431
1870
  }
1432
- commits.push(createNewView(newAtom, nativeRenderer, context, parentComponent, effect));
1871
+ commits.push({
1872
+ callback: patchUpdate,
1873
+ params: {
1874
+ oldAtom: oldAtom,
1875
+ newAtom,
1876
+ nativeRenderer,
1877
+ context,
1878
+ effect,
1879
+ parentComponent
1880
+ }
1881
+ });
1433
1882
  return startDiffAtom;
1434
1883
  }
1435
- function createNewView(start, nativeRenderer, context, parentComponent, effect) {
1436
- return function () {
1437
- buildView(nativeRenderer, parentComponent, start, context);
1438
- effect();
1439
- };
1884
+ function patchUpdate(params) {
1885
+ const { nativeRenderer, parentComponent, newAtom, context, effect } = params;
1886
+ buildView(nativeRenderer, parentComponent, newAtom, context);
1887
+ effect();
1440
1888
  }
1441
- function updateText(newAtom, oldAtom, nativeRenderer, context) {
1442
- return function (offset, needMove) {
1443
- const nativeNode = oldAtom.nativeNode;
1444
- newAtom.nativeNode = nativeNode;
1445
- if (needMove || newAtom.index - offset !== oldAtom.index) {
1446
- insertNode(nativeRenderer, newAtom, context);
1447
- }
1448
- context.host = nativeNode;
1449
- context.isParent = false;
1450
- };
1889
+ function updateText(params, offset, needMove) {
1890
+ const { oldAtom, newAtom, nativeRenderer, context } = params;
1891
+ const nativeNode = oldAtom.nativeNode;
1892
+ newAtom.nativeNode = nativeNode;
1893
+ if (needMove || newAtom.index - offset !== oldAtom.index) {
1894
+ insertNode(nativeRenderer, newAtom, context);
1895
+ }
1896
+ context.host = nativeNode;
1897
+ context.isParent = false;
1451
1898
  }
1452
- function updateElement(newAtom, oldAtom, nativeRenderer, context, parentComponent) {
1453
- return function (offset, needMove) {
1454
- newAtom.nativeNode = oldAtom.nativeNode;
1455
- if (needMove || newAtom.index - offset !== oldAtom.index) {
1456
- insertNode(nativeRenderer, newAtom, context);
1457
- }
1458
- context.host = newAtom.nativeNode;
1459
- context.isParent = false;
1460
- updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComponent, {
1461
- host: newAtom.nativeNode,
1462
- isParent: true,
1463
- rootHost: context.rootHost
1464
- });
1465
- };
1899
+ function updateElement(params, offset, needMove) {
1900
+ const { nativeRenderer, newAtom, oldAtom, context, parentComponent } = params;
1901
+ newAtom.nativeNode = oldAtom.nativeNode;
1902
+ if (needMove || newAtom.index - offset !== oldAtom.index) {
1903
+ insertNode(nativeRenderer, newAtom, context);
1904
+ }
1905
+ context.host = newAtom.nativeNode;
1906
+ context.isParent = false;
1907
+ updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComponent, {
1908
+ host: newAtom.nativeNode,
1909
+ isParent: true,
1910
+ rootHost: context.rootHost
1911
+ });
1466
1912
  }
1467
- function updateComponent(newAtom, reusedAtom, nativeRenderer, context) {
1468
- return function (offset, needMove) {
1469
- const component = reusedAtom.jsxNode;
1470
- const newProps = newAtom.jsxNode.props;
1471
- const portalHost = component.instance.$portalHost;
1472
- context = portalHost ? { isParent: true, host: portalHost, rootHost: portalHost } : context;
1473
- componentViewCache.set(component, Object.assign({ atom: newAtom }, context));
1474
- newAtom.jsxNode = component;
1475
- component.update(newProps, newTemplate => {
1476
- if (newTemplate) {
1477
- newAtom.child = createChildChain(newTemplate, newAtom.namespace);
1478
- }
1479
- if (newAtom.child) {
1480
- diff(nativeRenderer, component, newAtom.child, reusedAtom.child, context, needMove || newAtom.index - offset !== reusedAtom.index);
1481
- }
1482
- else if (reusedAtom.child) {
1483
- let atom = reusedAtom.child;
1484
- while (atom) {
1485
- cleanView(nativeRenderer, atom, true);
1486
- atom = atom.sibling;
1487
- }
1488
- }
1489
- }, (skipSubComponentDiff) => {
1490
- newAtom.child = reusedAtom.child;
1491
- reuseComponentView(nativeRenderer, newAtom.child, context, needMove || newAtom.index - offset !== reusedAtom.index, skipSubComponentDiff);
1492
- });
1493
- };
1913
+ function updateComponent(params, offset, needMove) {
1914
+ const { oldAtom, newAtom, nativeRenderer } = params;
1915
+ let context = params.context;
1916
+ const component = oldAtom.jsxNode;
1917
+ const portalHost = component.instance.$portalHost;
1918
+ context = portalHost ? { isParent: true, host: portalHost, rootHost: portalHost } : context;
1919
+ component.viewMetadata = Object.assign({ atom: newAtom }, context);
1920
+ const newProps = newAtom.jsxNode.props;
1921
+ newAtom.jsxNode = component;
1922
+ needMove = needMove || newAtom.index - offset !== oldAtom.index;
1923
+ const canUpdate = component.canUpdate(component.props, newProps);
1924
+ const propsIsChanged = hasChange(newProps, component.props);
1925
+ if (propsIsChanged) {
1926
+ component.updateProps(newProps);
1927
+ }
1928
+ if (canUpdate && (propsIsChanged || component.dirty)) {
1929
+ patchComponent(nativeRenderer, component, oldAtom.child, newAtom, context, needMove);
1930
+ const next = oldAtom.sibling;
1931
+ if (next && next.jsxNode instanceof Component) {
1932
+ const view = next.jsxNode.viewMetadata;
1933
+ view.host = context.host;
1934
+ view.isParent = context.isParent;
1935
+ }
1936
+ }
1937
+ else {
1938
+ newAtom.child = oldAtom.child;
1939
+ reuseComponentView(nativeRenderer, newAtom.child, context, needMove, true);
1940
+ }
1941
+ component.rendered();
1494
1942
  }
1495
1943
  function reuseComponentView(nativeRenderer, child, context, moveView, skipSubComponentDiff) {
1496
1944
  const updateContext = (atom) => {
1497
1945
  if (atom.jsxNode instanceof Component) {
1498
- if (skipSubComponentDiff || !moveView) {
1499
- let child = atom.child;
1500
- while (child) {
1501
- updateContext(child);
1502
- child = child.sibling;
1503
- }
1504
- }
1505
- else {
1506
- applyChanges(nativeRenderer, atom.jsxNode, atom, context, true);
1946
+ reuseComponentView(nativeRenderer, atom.child, context, moveView, skipSubComponentDiff);
1947
+ if (!skipSubComponentDiff) {
1948
+ deepUpdateByComponentDirtyTree(nativeRenderer, atom.jsxNode, moveView);
1507
1949
  }
1508
1950
  }
1509
1951
  else {
@@ -1524,7 +1966,7 @@ function reuseElementChildrenView(nativeRenderer, atom, context, skipSubComponen
1524
1966
  let child = atom.child;
1525
1967
  while (child) {
1526
1968
  if (child.jsxNode instanceof Component) {
1527
- updateView(nativeRenderer, child.jsxNode, false);
1969
+ deepUpdateByComponentDirtyTree(nativeRenderer, child.jsxNode, false);
1528
1970
  }
1529
1971
  else {
1530
1972
  reuseElementChildrenView(nativeRenderer, child);
@@ -1571,7 +2013,7 @@ function componentRender(nativeRenderer, component, from, context) {
1571
2013
  component.render((template, portalHost) => {
1572
2014
  from.child = createChildChain(template, from.namespace);
1573
2015
  context = portalHost ? { isParent: true, host: portalHost, rootHost: portalHost } : context;
1574
- componentViewCache.set(component, Object.assign({ atom: from }, context));
2016
+ component.viewMetadata = Object.assign({ atom: from }, context);
1575
2017
  let child = from.child;
1576
2018
  while (child) {
1577
2019
  buildView(nativeRenderer, component, child, context);
@@ -1596,14 +2038,14 @@ function createChainByJSXNode(type, jsxNode, nodeType, prevAtom, namespace, key)
1596
2038
  }
1597
2039
  function createChainByNode(jsxNode, prevAtom, elementNamespace) {
1598
2040
  const type = typeof jsxNode;
1599
- if (jsxNode !== null && type !== 'undefined' && type !== 'boolean') {
1600
- if (typeof jsxNode === 'string') {
2041
+ if (jsxNode != null && type !== 'boolean') {
2042
+ if (type === 'string') {
1601
2043
  return createChainByJSXNode(TextAtomType, jsxNode, jsxNode, prevAtom, elementNamespace);
1602
2044
  }
1603
- if (Array.isArray(jsxNode)) {
1604
- return createChainByChildren(jsxNode, prevAtom, elementNamespace);
1605
- }
1606
2045
  if (type === 'object') {
2046
+ if (Array.isArray(jsxNode)) {
2047
+ return createChainByChildren(jsxNode, prevAtom, elementNamespace);
2048
+ }
1607
2049
  const nodeType = typeof jsxNode.type;
1608
2050
  if (nodeType === 'string') {
1609
2051
  return createChainByJSXNode(ElementAtomType, jsxNode, jsxNode.type, prevAtom, elementNamespace || ElementNamespaceMap[jsxNode.type], jsxNode.key);
@@ -1643,6 +2085,12 @@ function insertNode(nativeRenderer, atom, context) {
1643
2085
  nativeRenderer.insertAfter(atom.nativeNode, context.host, atom.namespace);
1644
2086
  }
1645
2087
  }
2088
+ function createElementChildren(type, children, namespace) {
2089
+ if (type === 'foreignObject' && namespace === ElementNamespaceMap.svg) {
2090
+ return createChildChain(children, void 0);
2091
+ }
2092
+ return createChildChain(children, namespace);
2093
+ }
1646
2094
  function createElement(nativeRenderer, atom, parentComponent, context) {
1647
2095
  const { namespace, jsxNode } = atom;
1648
2096
  const nativeNode = nativeRenderer.createElement(jsxNode.type, namespace);
@@ -1650,7 +2098,7 @@ function createElement(nativeRenderer, atom, parentComponent, context) {
1650
2098
  let bindingRefs;
1651
2099
  for (const key in props) {
1652
2100
  if (key === 'children') {
1653
- atom.child = createChildChain(jsxNode.props.children, namespace);
2101
+ atom.child = createElementChildren(jsxNode.type, props.children, namespace);
1654
2102
  continue;
1655
2103
  }
1656
2104
  if (key === 'class') {
@@ -1708,46 +2156,69 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
1708
2156
  reuseElementChildrenView(nativeRenderer, newAtom);
1709
2157
  return;
1710
2158
  }
1711
- const changes = getObjectChanges(newVNode.props, oldVNode.props);
1712
2159
  let unBindRefs;
1713
2160
  let bindRefs;
1714
2161
  let updatedChildren = false;
1715
- let len = changes.remove.length;
1716
- for (let i = 0; i < len; i++) {
1717
- const [key, value] = changes.remove[i];
2162
+ comparePropsWithCallbacks(oldVNode.props, newVNode.props, (key, oldValue) => {
1718
2163
  if (key === 'children') {
1719
2164
  updatedChildren = true;
1720
2165
  cleanElementChildren(oldAtom, nativeRenderer);
1721
- continue;
2166
+ return;
1722
2167
  }
1723
2168
  if (key === 'class') {
1724
2169
  nativeRenderer.setClass(nativeNode, '', isSvg);
1725
- continue;
2170
+ return;
1726
2171
  }
1727
2172
  if (key === 'style') {
1728
- for (const styleName in styleToObject(value)) {
2173
+ for (const styleName in styleToObject(oldValue)) {
1729
2174
  nativeRenderer.removeStyle(nativeNode, styleName, isSvg);
1730
2175
  }
1731
- continue;
2176
+ return;
1732
2177
  }
1733
2178
  if (listenerReg.test(key)) {
1734
- if (typeof value === 'function') {
1735
- nativeRenderer.unListen(nativeNode, key, value, isSvg);
2179
+ if (typeof oldValue === 'function') {
2180
+ nativeRenderer.unListen(nativeNode, key, oldValue, isSvg);
1736
2181
  }
1737
- continue;
2182
+ return;
1738
2183
  }
1739
2184
  if (key === refKey) {
1740
- unBindRefs = value;
1741
- continue;
2185
+ unBindRefs = oldValue;
2186
+ return;
1742
2187
  }
1743
2188
  nativeRenderer.removeProperty(nativeNode, key, isSvg);
1744
- }
1745
- len = changes.replace.length;
1746
- for (let i = 0; i < len; i++) {
1747
- const [key, newValue, oldValue] = changes.replace[i];
2189
+ }, (key, value) => {
2190
+ if (key === 'children') {
2191
+ updatedChildren = true;
2192
+ newAtom.child = createElementChildren(newVNode.type, value, isSvg);
2193
+ buildElementChildren(newAtom, nativeRenderer, parentComponent, context);
2194
+ return;
2195
+ }
2196
+ if (key === 'class') {
2197
+ nativeRenderer.setClass(nativeNode, classToString(value), isSvg);
2198
+ return;
2199
+ }
2200
+ if (key === 'style') {
2201
+ const styleObj = styleToObject(value);
2202
+ for (const styleName in styleObj) {
2203
+ nativeRenderer.setStyle(nativeNode, styleName, styleObj[styleName], isSvg);
2204
+ }
2205
+ return;
2206
+ }
2207
+ if (listenerReg.test(key)) {
2208
+ if (typeof value === 'function') {
2209
+ nativeRenderer.listen(nativeNode, key, value, isSvg);
2210
+ }
2211
+ return;
2212
+ }
2213
+ if (key === refKey) {
2214
+ bindRefs = value;
2215
+ return;
2216
+ }
2217
+ nativeRenderer.setProperty(nativeNode, key, value, isSvg);
2218
+ }, (key, newValue, oldValue) => {
1748
2219
  if (key === 'children') {
1749
2220
  updatedChildren = true;
1750
- newAtom.child = createChildChain(newValue, isSvg);
2221
+ newAtom.child = createElementChildren(newVNode.type, newValue, isSvg);
1751
2222
  if (!newAtom.child) {
1752
2223
  cleanElementChildren(oldAtom, nativeRenderer);
1753
2224
  }
@@ -1757,7 +2228,7 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
1757
2228
  else {
1758
2229
  diff(nativeRenderer, parentComponent, newAtom.child, oldAtom.child, context, false);
1759
2230
  }
1760
- continue;
2231
+ return;
1761
2232
  }
1762
2233
  if (key === 'class') {
1763
2234
  const oldClassName = classToString(oldValue);
@@ -1765,62 +2236,30 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
1765
2236
  if (oldClassName !== newClassName) {
1766
2237
  nativeRenderer.setClass(nativeNode, newClassName, isSvg);
1767
2238
  }
1768
- continue;
2239
+ return;
1769
2240
  }
1770
2241
  if (key === 'style') {
1771
- const styleChanges = getObjectChanges(styleToObject(newValue) || {}, styleToObject(oldValue) || {});
1772
- for (const [styleName] of styleChanges.remove) {
2242
+ comparePropsWithCallbacks(styleToObject(oldValue), styleToObject(newValue), styleName => {
1773
2243
  nativeRenderer.removeStyle(nativeNode, styleName, isSvg);
1774
- }
1775
- for (const [styleName, styleValue] of [...styleChanges.add, ...styleChanges.replace]) {
2244
+ }, (styleName, styleValue) => {
1776
2245
  nativeRenderer.setStyle(nativeNode, styleName, styleValue, isSvg);
1777
- }
1778
- continue;
2246
+ }, (styleName, styleValue) => {
2247
+ nativeRenderer.setStyle(nativeNode, styleName, styleValue, isSvg);
2248
+ });
2249
+ return;
1779
2250
  }
1780
2251
  if (listenerReg.test(key)) {
1781
2252
  nativeRenderer.unListen(nativeNode, key, oldValue, isSvg);
1782
2253
  nativeRenderer.listen(nativeNode, key, newValue, isSvg);
1783
- continue;
2254
+ return;
1784
2255
  }
1785
2256
  if (key === refKey) {
1786
2257
  unBindRefs = oldValue;
1787
2258
  bindRefs = newValue;
1788
- continue;
2259
+ return;
1789
2260
  }
1790
2261
  nativeRenderer.setProperty(nativeNode, key, newValue, isSvg);
1791
- }
1792
- len = changes.add.length;
1793
- for (let i = 0; i < len; i++) {
1794
- const [key, value] = changes.add[i];
1795
- if (key === 'children') {
1796
- updatedChildren = true;
1797
- newAtom.child = createChildChain(value, isSvg);
1798
- buildElementChildren(newAtom, nativeRenderer, parentComponent, context);
1799
- continue;
1800
- }
1801
- if (key === 'class') {
1802
- nativeRenderer.setClass(nativeNode, classToString(value), isSvg);
1803
- continue;
1804
- }
1805
- if (key === 'style') {
1806
- const styleObj = styleToObject(value);
1807
- for (const styleName in styleObj) {
1808
- nativeRenderer.setStyle(nativeNode, styleName, styleObj[styleName], isSvg);
1809
- }
1810
- continue;
1811
- }
1812
- if (listenerReg.test(key)) {
1813
- if (typeof value === 'function') {
1814
- nativeRenderer.listen(nativeNode, key, value, isSvg);
1815
- }
1816
- continue;
1817
- }
1818
- if (key === refKey) {
1819
- bindRefs = value;
1820
- continue;
1821
- }
1822
- nativeRenderer.setProperty(nativeNode, key, value, isSvg);
1823
- }
2262
+ });
1824
2263
  if (!updatedChildren) {
1825
2264
  newAtom.child = oldAtom.child;
1826
2265
  reuseElementChildrenView(nativeRenderer, newAtom);
@@ -1863,133 +2302,6 @@ class RootComponent extends Component {
1863
2302
  }
1864
2303
  }
1865
2304
 
1866
- /**
1867
- * 组件状态管理器
1868
- * @param state 初始状态
1869
- * @example
1870
- * ```tsx
1871
- * function App() {
1872
- * // 初始化状态
1873
- * const state = createSignal(1)
1874
- *
1875
- * return () => {
1876
- * <div>
1877
- * <div>当前值为:{state()}</div>
1878
- * <div>
1879
- * <button type="button" onClick={() => {
1880
- * // 当点击时更新状态
1881
- * state.set(state() + 1)
1882
- * }
1883
- * }>updateState</button>
1884
- * </div>
1885
- * </div>
1886
- * }
1887
- * }
1888
- */
1889
- function createSignal(state) {
1890
- const subscribers = new Set();
1891
- function signal() {
1892
- const listener = getCurrentListener();
1893
- if (listener && !subscribers.has(listener)) {
1894
- listener.destroyCallbacks.push(() => {
1895
- subscribers.delete(listener);
1896
- });
1897
- subscribers.add(listener);
1898
- }
1899
- return state;
1900
- }
1901
- signal.set = function (newValue) {
1902
- if (newValue === state) {
1903
- return;
1904
- }
1905
- state = newValue;
1906
- const listeners = Array.from(subscribers);
1907
- listeners.forEach(listener => listener.effect());
1908
- };
1909
- return signal;
1910
- }
1911
- /**
1912
- * 使用派生值,Viewfly 会收集回调函数内同步执行时访问的 Signal,
1913
- * 并在你获取 createDerived 函数返回的 Signal 的值时,自动计算最新的值。
1914
- *
1915
- * @param fn
1916
- * @param isContinue 可选的停止函数,在每次值更新后调用,当返回值为 false 时,将不再监听依赖的变化
1917
- */
1918
- function computed(fn, isContinue) {
1919
- let isStop = false;
1920
- function canListen(value) {
1921
- if (isContinue) {
1922
- const b = isContinue(value);
1923
- if (b === false) {
1924
- listener.destroy();
1925
- return false;
1926
- }
1927
- }
1928
- return true;
1929
- }
1930
- const listener = new Listener(() => {
1931
- if (isStop) {
1932
- return;
1933
- }
1934
- isStop = true;
1935
- listener.destroy();
1936
- pushListener(listener);
1937
- const value = fn();
1938
- popListener();
1939
- signal.set(value);
1940
- canListen(value);
1941
- isStop = false;
1942
- });
1943
- pushListener(listener);
1944
- const value = fn();
1945
- const signal = createSignal(value);
1946
- popListener();
1947
- isStop = false;
1948
- if (canListen(value)) {
1949
- registryComponentDestroyCallback(() => listener.destroy());
1950
- }
1951
- return signal;
1952
- }
1953
- const createDerived = computed;
1954
- /* eslint-enable max-len*/
1955
- function watch(deps, callback) {
1956
- let prevFn;
1957
- const isArray = Array.isArray(deps);
1958
- const effect = new Listener(function () {
1959
- if (prevFn) {
1960
- prevFn();
1961
- }
1962
- const newValue = isArray ? deps.map(fn => fn()) : deps();
1963
- prevFn = callback(newValue, oldValue);
1964
- oldValue = newValue;
1965
- });
1966
- pushListener(effect);
1967
- let oldValue = isArray ? deps.map(fn => fn()) : deps();
1968
- popListener();
1969
- let isUnWatch = false;
1970
- function unWatch() {
1971
- if (isUnWatch) {
1972
- return;
1973
- }
1974
- isUnWatch = true;
1975
- if (prevFn) {
1976
- prevFn();
1977
- }
1978
- effect.destroy();
1979
- }
1980
- registryComponentDestroyCallback(unWatch);
1981
- return unWatch;
1982
- }
1983
- function registryComponentDestroyCallback(fn) {
1984
- const component = getSetupContext(false);
1985
- if (component) {
1986
- if (!component.unmountedCallbacks) {
1987
- component.unmountedCallbacks = [];
1988
- }
1989
- component.unmountedCallbacks.push(fn);
1990
- }
1991
- }
1992
-
1993
2305
  const viewflyErrorFn = makeError('Viewfly');
1994
2306
  function viewfly(config) {
1995
2307
  const { context, nativeRenderer, autoUpdate, root } = Object.assign({ autoUpdate: true }, config);
@@ -1998,7 +2310,7 @@ function viewfly(config) {
1998
2310
  let appHost = null;
1999
2311
  const rootProviders = [];
2000
2312
  const rootComponent = new RootComponent(() => {
2001
- const rootContext = createContext(rootProviders, void 0, context);
2313
+ const rootContext = createContext(rootProviders, null, context);
2002
2314
  return () => {
2003
2315
  return jsx(rootContext, {
2004
2316
  children: destroyed ? null : root
@@ -2077,4 +2389,122 @@ function viewfly(config) {
2077
2389
  return app;
2078
2390
  }
2079
2391
 
2080
- export { Component, DynamicRef, ElementNamespaceMap, ForwardRef, Fragment, Inject, InjectFlags, Injectable, InjectionToken, Injector, JSXNodeFactory, NativeRenderer, NullInjector, Optional, Prop, ReflectiveInjector, RootComponent, Scope, Self, SkipSelf, StaticRef, THROW_IF_NOT_FOUND, Type, computed, createContext, createDerived, createDynamicRef, createRef, createRenderer, createSignal, forwardRef, getCurrentInstance, getSetupContext, inject, jsx, jsxs, makeError, normalizeProvider, onMounted, onPropsChanged, onUnmounted, onUpdated, viewfly, watch, withMemo };
2392
+ function computed(callback, isContinue) {
2393
+ let isStop = false;
2394
+ const dep = new Dep(() => {
2395
+ if (isStop) {
2396
+ return;
2397
+ }
2398
+ isStop = true;
2399
+ dep.destroy();
2400
+ pushDepContext(dep);
2401
+ const value = callback();
2402
+ popDepContext();
2403
+ internalWrite(() => {
2404
+ proxy.value = value;
2405
+ });
2406
+ canListen(value);
2407
+ isStop = false;
2408
+ });
2409
+ pushDepContext(dep);
2410
+ const value = callback();
2411
+ popDepContext();
2412
+ const proxy = new Proxy({
2413
+ value
2414
+ }, readonlyProxyHandler);
2415
+ function canListen(value) {
2416
+ if (isContinue) {
2417
+ const b = isContinue(value);
2418
+ if (b === false) {
2419
+ dep.destroy();
2420
+ return false;
2421
+ }
2422
+ }
2423
+ return true;
2424
+ }
2425
+ if (!canListen(value)) {
2426
+ return proxy;
2427
+ }
2428
+ registryComponentDestroyCallback(() => {
2429
+ dep.destroy();
2430
+ });
2431
+ return proxy;
2432
+ }
2433
+
2434
+ const defaultShallowObjectReactiveHandler = new ObjectReactiveHandler({
2435
+ readonly: false,
2436
+ shallow: true
2437
+ });
2438
+ const defaultShallowArrayReactiveHandler = new ArrayReactiveHandler({
2439
+ readonly: false,
2440
+ shallow: true
2441
+ });
2442
+ const defaultShallowMapReactiveHandler = new MapReactiveHandler({
2443
+ readonly: false,
2444
+ shallow: true
2445
+ });
2446
+ const defaultShallowSetReactiveHandler = new SetReactiveHandler({
2447
+ readonly: false,
2448
+ shallow: true
2449
+ });
2450
+ function shallowReactive(raw) {
2451
+ if (isReactive(raw)) {
2452
+ return raw;
2453
+ }
2454
+ let proxy = rawToProxyCache.get(raw);
2455
+ if (proxy) {
2456
+ return proxy;
2457
+ }
2458
+ const type = getStringType(raw);
2459
+ switch (type) {
2460
+ case '[object Object]':
2461
+ proxy = new Proxy(raw, defaultShallowObjectReactiveHandler);
2462
+ break;
2463
+ case '[object Array]':
2464
+ proxy = new Proxy(raw, defaultShallowArrayReactiveHandler);
2465
+ break;
2466
+ case '[object Set]':
2467
+ case '[object WeakSet]':
2468
+ proxy = new Proxy(raw, defaultShallowSetReactiveHandler);
2469
+ break;
2470
+ case '[object Map]':
2471
+ case '[object WeakMap]':
2472
+ proxy = new Proxy(raw, defaultShallowMapReactiveHandler);
2473
+ break;
2474
+ default:
2475
+ return raw;
2476
+ }
2477
+ rawToProxyCache.set(raw, proxy);
2478
+ proxyToRawCache.set(proxy, raw);
2479
+ return proxy;
2480
+ }
2481
+
2482
+ function watch(trigger, callback) {
2483
+ let prevFn;
2484
+ const dep = new Dep(() => {
2485
+ pushDepContext(dep);
2486
+ const newValue = trigger();
2487
+ popDepContext();
2488
+ if (newValue === oldValue) {
2489
+ return;
2490
+ }
2491
+ if (prevFn) {
2492
+ prevFn();
2493
+ }
2494
+ prevFn = callback(newValue, oldValue);
2495
+ oldValue = newValue;
2496
+ });
2497
+ pushDepContext(dep);
2498
+ let oldValue = trigger();
2499
+ popDepContext();
2500
+ dep.destroyCallbacks.push(() => {
2501
+ prevFn === null || prevFn === void 0 ? void 0 : prevFn();
2502
+ });
2503
+ function unWatch() {
2504
+ dep.destroy();
2505
+ }
2506
+ registryComponentDestroyCallback(unWatch);
2507
+ return unWatch;
2508
+ }
2509
+
2510
+ export { ArrayReactiveHandler, Component, Dep, DynamicRef, ElementNamespaceMap, ForwardRef, Fragment, Inject, InjectFlags, Injectable, InjectionToken, Injector, JSXNodeFactory, MapReactiveHandler, NativeRenderer, NullInjector, ObjectReactiveHandler, Optional, Prop, ReflectiveInjector, RootComponent, Scope, Self, SetReactiveHandler, SkipSelf, StaticRef, THROW_IF_NOT_FOUND, TrackOpTypes, TriggerOpTypes, Type, comparePropsWithCallbacks, computed, createContext, createDynamicRef, createRef, createRenderer, 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, viewfly, watch, withAnnotation, withMemo };