@viewfly/core 1.2.2 → 1.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bundles/index.js CHANGED
@@ -603,79 +603,6 @@ class ReflectiveInjector {
603
603
 
604
604
  const Type = Function;
605
605
 
606
- const refKey = 'ref';
607
- function getObjectChanges(newProps, oldProps) {
608
- const changes = {
609
- remove: [],
610
- add: [],
611
- replace: []
612
- };
613
- for (const key in newProps) {
614
- const leftValue = newProps[key];
615
- const rightValue = oldProps[key];
616
- if (Reflect.has(oldProps, key)) {
617
- if (leftValue !== rightValue) {
618
- changes.replace.push([key, leftValue, rightValue]);
619
- }
620
- continue;
621
- }
622
- changes.add.push([key, leftValue]);
623
- }
624
- for (const key in oldProps) {
625
- if (!Reflect.has(newProps, key)) {
626
- changes.remove.push([key, oldProps[key]]);
627
- }
628
- }
629
- return changes;
630
- }
631
- function classToString(config) {
632
- if (typeof config === 'string') {
633
- return config;
634
- }
635
- if (!config) {
636
- return '';
637
- }
638
- if (Array.isArray(config)) {
639
- const classes = [];
640
- for (const i of config) {
641
- const v = classToString(i);
642
- if (v) {
643
- classes.push(v);
644
- }
645
- }
646
- return classes.join(' ');
647
- }
648
- if (typeof config === 'object') {
649
- if (config.toString !== Object.prototype.toString && !config.toString.toString().includes('[native code]')) {
650
- return config.toString();
651
- }
652
- const classes = [];
653
- for (const key in config) {
654
- if ({}.hasOwnProperty.call(config, key) && config[key]) {
655
- classes.push(key);
656
- }
657
- }
658
- return classes.join(' ');
659
- }
660
- return '';
661
- }
662
- function styleToObject(style) {
663
- if (typeof style !== 'string') {
664
- return style;
665
- }
666
- const obj = {};
667
- style.split(';').map(s => s.split(':')).forEach(v => {
668
- if (!v[0] || !v[1]) {
669
- return;
670
- }
671
- obj[v[0].trim()] = v[1].trim();
672
- });
673
- return obj;
674
- }
675
- const TextAtomType = Symbol('Text');
676
- const ElementAtomType = Symbol('Element');
677
- const ComponentAtomType = Symbol('Component');
678
-
679
606
  class Listener {
680
607
  constructor(effect) {
681
608
  Object.defineProperty(this, "effect", {
@@ -922,109 +849,25 @@ class Component {
922
849
  return this._changed;
923
850
  }
924
851
  constructor(parentComponent, type, props, key) {
925
- Object.defineProperty(this, "parentComponent", {
926
- enumerable: true,
927
- configurable: true,
928
- writable: true,
929
- value: parentComponent
930
- });
931
- Object.defineProperty(this, "type", {
932
- enumerable: true,
933
- configurable: true,
934
- writable: true,
935
- value: type
936
- });
937
- Object.defineProperty(this, "props", {
938
- enumerable: true,
939
- configurable: true,
940
- writable: true,
941
- value: props
942
- });
943
- Object.defineProperty(this, "key", {
944
- enumerable: true,
945
- configurable: true,
946
- writable: true,
947
- value: key
948
- });
949
- Object.defineProperty(this, "instance", {
950
- enumerable: true,
951
- configurable: true,
952
- writable: true,
953
- value: void 0
954
- });
955
- Object.defineProperty(this, "changedSubComponents", {
956
- enumerable: true,
957
- configurable: true,
958
- writable: true,
959
- value: new Set()
960
- });
961
- Object.defineProperty(this, "unmountedCallbacks", {
962
- enumerable: true,
963
- configurable: true,
964
- writable: true,
965
- value: void 0
966
- });
967
- Object.defineProperty(this, "mountCallbacks", {
968
- enumerable: true,
969
- configurable: true,
970
- writable: true,
971
- value: void 0
972
- });
973
- Object.defineProperty(this, "propsChangedCallbacks", {
974
- enumerable: true,
975
- configurable: true,
976
- writable: true,
977
- value: void 0
978
- });
979
- Object.defineProperty(this, "updatedCallbacks", {
980
- enumerable: true,
981
- configurable: true,
982
- writable: true,
983
- value: void 0
984
- });
985
- Object.defineProperty(this, "updatedDestroyCallbacks", {
986
- enumerable: true,
987
- configurable: true,
988
- writable: true,
989
- value: void 0
990
- });
991
- Object.defineProperty(this, "propsChangedDestroyCallbacks", {
992
- enumerable: true,
993
- configurable: true,
994
- writable: true,
995
- value: void 0
996
- });
997
- Object.defineProperty(this, "_dirty", {
998
- enumerable: true,
999
- configurable: true,
1000
- writable: true,
1001
- value: true
1002
- });
1003
- Object.defineProperty(this, "_changed", {
1004
- enumerable: true,
1005
- configurable: true,
1006
- writable: true,
1007
- value: true
1008
- });
1009
- Object.defineProperty(this, "isFirstRendering", {
1010
- enumerable: true,
1011
- configurable: true,
1012
- writable: true,
1013
- value: true
1014
- });
1015
- Object.defineProperty(this, "refs", {
1016
- enumerable: true,
1017
- configurable: true,
1018
- writable: true,
1019
- value: null
1020
- });
1021
- Object.defineProperty(this, "listener", {
1022
- enumerable: true,
1023
- configurable: true,
1024
- writable: true,
1025
- value: new Listener(() => {
1026
- this.markAsDirtied();
1027
- })
852
+ this.parentComponent = parentComponent;
853
+ this.type = type;
854
+ this.props = props;
855
+ this.key = key;
856
+ this.instance = null;
857
+ this.changedSubComponents = new Set();
858
+ this.viewMetadata = null;
859
+ this.unmountedCallbacks = null;
860
+ this.mountCallbacks = null;
861
+ this.propsChangedCallbacks = null;
862
+ this.updatedCallbacks = null;
863
+ this.updatedDestroyCallbacks = null;
864
+ this.propsChangedDestroyCallbacks = null;
865
+ this._dirty = true;
866
+ this._changed = false;
867
+ this.isFirstRendering = true;
868
+ this.refs = null;
869
+ this.listener = new Listener(() => {
870
+ this.markAsDirtied();
1028
871
  });
1029
872
  }
1030
873
  markAsDirtied() {
@@ -1039,7 +882,7 @@ class Component {
1039
882
  return;
1040
883
  }
1041
884
  this._changed = true;
1042
- if (this.parentComponent instanceof Component) {
885
+ if (this.parentComponent) {
1043
886
  this.parentComponent.markAsChanged(this);
1044
887
  }
1045
888
  }
@@ -1085,62 +928,54 @@ class Component {
1085
928
  update(template, this.instance.$portalHost);
1086
929
  this.rendered();
1087
930
  }
1088
- update(newProps, updateChildren, reuseChildren) {
1089
- const oldProps = this.props;
1090
- if (newProps !== oldProps) {
1091
- const { add, remove, replace } = getObjectChanges(newProps, oldProps);
1092
- if (add.length || remove.length || replace.length) {
1093
- this.invokePropsChangedHooks(newProps);
1094
- }
1095
- else if (!this.dirty) {
1096
- this.props = newProps;
1097
- reuseChildren(false);
1098
- this.rendered();
1099
- return;
1100
- }
1101
- const newRefs = toRefs(newProps.ref);
1102
- if (this.refs) {
1103
- for (const oldRef of this.refs) {
1104
- if (!newRefs.includes(oldRef)) {
1105
- oldRef.unBind(this.instance);
1106
- }
931
+ updateProps(newProps) {
932
+ this.invokePropsChangedHooks(newProps);
933
+ const newRefs = toRefs(newProps.ref);
934
+ if (this.refs) {
935
+ for (const oldRef of this.refs) {
936
+ if (!newRefs.includes(oldRef)) {
937
+ oldRef.unBind(this.instance);
1107
938
  }
1108
939
  }
1109
- for (const newRef of newRefs) {
1110
- newRef.bind(this.instance);
1111
- }
1112
- if (newRefs.length) {
1113
- this.refs = newRefs;
1114
- }
1115
940
  }
941
+ for (const newRef of newRefs) {
942
+ newRef.bind(this.instance);
943
+ }
944
+ if (newRefs.length) {
945
+ this.refs = newRefs;
946
+ }
947
+ }
948
+ canUpdate(oldProps, newProps) {
1116
949
  if (typeof this.instance.$useMemo === 'function') {
1117
950
  if (this.instance.$useMemo(newProps, oldProps)) {
1118
- reuseChildren(true);
1119
- this.rendered();
1120
- return;
951
+ return false;
1121
952
  }
1122
953
  }
954
+ return true;
955
+ }
956
+ rerender() {
1123
957
  this.listener.destroy();
1124
958
  pushListener(this.listener);
1125
959
  const template = this.instance.$render();
1126
960
  popListener();
1127
- updateChildren(template);
1128
- this.rendered();
961
+ return template;
1129
962
  }
1130
963
  destroy() {
1131
- var _a, _b, _c;
1132
964
  this.listener.destroy();
1133
- (_a = this.updatedDestroyCallbacks) === null || _a === void 0 ? void 0 : _a.forEach(fn => {
1134
- fn();
1135
- });
1136
- (_b = this.propsChangedDestroyCallbacks) === null || _b === void 0 ? void 0 : _b.forEach(fn => {
1137
- fn();
1138
- });
1139
- (_c = this.unmountedCallbacks) === null || _c === void 0 ? void 0 : _c.forEach(fn => {
1140
- fn();
1141
- });
1142
- if (this.parentComponent instanceof Component) {
1143
- this.parentComponent.changedSubComponents.delete(this);
965
+ if (this.updatedDestroyCallbacks) {
966
+ this.updatedDestroyCallbacks.forEach(fn => {
967
+ fn();
968
+ });
969
+ }
970
+ if (this.propsChangedDestroyCallbacks) {
971
+ this.propsChangedDestroyCallbacks.forEach(fn => {
972
+ fn();
973
+ });
974
+ }
975
+ if (this.unmountedCallbacks) {
976
+ this.unmountedCallbacks.forEach(fn => {
977
+ fn();
978
+ });
1144
979
  }
1145
980
  this.parentComponent =
1146
981
  this.propsChangedDestroyCallbacks =
@@ -1149,7 +984,6 @@ class Component {
1149
984
  this.updatedCallbacks =
1150
985
  this.propsChangedCallbacks =
1151
986
  this.unmountedCallbacks = null;
1152
- this.changedSubComponents.clear();
1153
987
  }
1154
988
  rendered() {
1155
989
  this.changedSubComponents.clear();
@@ -1162,7 +996,7 @@ class Component {
1162
996
  }
1163
997
  if (this.changed) {
1164
998
  Promise.resolve().then(() => {
1165
- if (this.parentComponent instanceof Component) {
999
+ if (this.parentComponent) {
1166
1000
  this.parentComponent.markAsChanged(this);
1167
1001
  }
1168
1002
  });
@@ -1351,11 +1185,89 @@ function withMemo(canUseMemo, render) {
1351
1185
  };
1352
1186
  }
1353
1187
 
1188
+ function hasChange(newProps, oldProps) {
1189
+ const newKeys = Object.keys(oldProps);
1190
+ const oldKeys = Object.keys(newProps);
1191
+ if (oldKeys.length !== newKeys.length) {
1192
+ return true;
1193
+ }
1194
+ const len = oldKeys.length;
1195
+ for (let i = 0; i < len; i++) {
1196
+ const key = newKeys[i];
1197
+ if (newProps[key] !== oldProps[key]) {
1198
+ return true;
1199
+ }
1200
+ }
1201
+ return false;
1202
+ }
1203
+ const refKey = 'ref';
1204
+ function comparePropsWithCallbacks(oldProps, newProps, onDeleted, onAdded, onUpdated) {
1205
+ for (const key in oldProps) {
1206
+ if (!(key in newProps)) {
1207
+ onDeleted(key, oldProps[key]);
1208
+ }
1209
+ }
1210
+ for (const key in newProps) {
1211
+ if (!(key in oldProps)) {
1212
+ onAdded(key, newProps[key]);
1213
+ }
1214
+ else if (oldProps[key] !== newProps[key]) {
1215
+ onUpdated(key, newProps[key], oldProps[key]);
1216
+ }
1217
+ }
1218
+ }
1219
+ function classToString(config) {
1220
+ if (typeof config === 'string') {
1221
+ return config;
1222
+ }
1223
+ if (!config) {
1224
+ return '';
1225
+ }
1226
+ if (Array.isArray(config)) {
1227
+ const classes = [];
1228
+ for (const i of config) {
1229
+ const v = classToString(i);
1230
+ if (v) {
1231
+ classes.push(v);
1232
+ }
1233
+ }
1234
+ return classes.join(' ');
1235
+ }
1236
+ if (typeof config === 'object') {
1237
+ if (config.toString !== Object.prototype.toString && !config.toString.toString().includes('[native code]')) {
1238
+ return config.toString();
1239
+ }
1240
+ const classes = [];
1241
+ for (const key in config) {
1242
+ if ({}.hasOwnProperty.call(config, key) && config[key]) {
1243
+ classes.push(key);
1244
+ }
1245
+ }
1246
+ return classes.join(' ');
1247
+ }
1248
+ return '';
1249
+ }
1250
+ function styleToObject(style) {
1251
+ if (typeof style !== 'string') {
1252
+ return style || {};
1253
+ }
1254
+ const obj = {};
1255
+ style.split(';').map(s => s.split(':')).forEach(v => {
1256
+ if (!v[0] || !v[1]) {
1257
+ return;
1258
+ }
1259
+ obj[v[0].trim()] = v[1].trim();
1260
+ });
1261
+ return obj;
1262
+ }
1263
+ const TextAtomType = Symbol('Text');
1264
+ const ElementAtomType = Symbol('Element');
1265
+ const ComponentAtomType = Symbol('Component');
1266
+
1354
1267
  const ElementNamespaceMap = {
1355
1268
  svg: 'svg',
1356
1269
  math: 'mathml',
1357
1270
  };
1358
- const componentViewCache = new WeakMap();
1359
1271
  const listenerReg = /^on[A-Z]/;
1360
1272
  function createRenderer(component, nativeRenderer, namespace) {
1361
1273
  let isInit = true;
@@ -1379,7 +1291,7 @@ function createRenderer(component, nativeRenderer, namespace) {
1379
1291
  });
1380
1292
  }
1381
1293
  else {
1382
- updateView(nativeRenderer, component, false);
1294
+ deepUpdateByComponentDirtyTree(nativeRenderer, component, false);
1383
1295
  }
1384
1296
  };
1385
1297
  }
@@ -1404,37 +1316,39 @@ function buildElementChildren(atom, nativeRenderer, parentComponent, context) {
1404
1316
  child = child.sibling;
1405
1317
  }
1406
1318
  }
1407
- function updateView(nativeRenderer, component, needMove) {
1319
+ function patchComponent(nativeRenderer, component, oldChildAtom, newAtom, context, needMove) {
1320
+ const newTemplate = component.rerender();
1321
+ newAtom.child = createChildChain(newTemplate, newAtom.namespace);
1322
+ diff(nativeRenderer, component, newAtom.child, oldChildAtom, context, needMove);
1323
+ }
1324
+ function deepUpdateByComponentDirtyTree(nativeRenderer, component, needMove) {
1408
1325
  if (component.dirty) {
1409
- const { atom, host, isParent, rootHost } = componentViewCache.get(component);
1410
- applyChanges(nativeRenderer, component, atom, {
1411
- host,
1412
- isParent,
1413
- rootHost
1414
- }, needMove);
1326
+ const canUpdate = component.canUpdate(component.props, component.props);
1327
+ if (canUpdate) {
1328
+ const { atom, host, isParent, rootHost } = component.viewMetadata;
1329
+ const context = {
1330
+ host,
1331
+ isParent,
1332
+ rootHost
1333
+ };
1334
+ const diffAtom = atom.child;
1335
+ patchComponent(nativeRenderer, component, diffAtom, atom, context, needMove);
1336
+ const next = atom.sibling;
1337
+ if (next && next.jsxNode instanceof Component) {
1338
+ const view = next.jsxNode.viewMetadata;
1339
+ view.host = context.host;
1340
+ view.isParent = context.isParent;
1341
+ }
1342
+ }
1343
+ component.rendered();
1415
1344
  }
1416
1345
  else if (component.changed) {
1417
1346
  component.changedSubComponents.forEach(child => {
1418
- updateView(nativeRenderer, child, needMove);
1347
+ deepUpdateByComponentDirtyTree(nativeRenderer, child, needMove);
1419
1348
  });
1420
1349
  component.rendered();
1421
1350
  }
1422
1351
  }
1423
- function applyChanges(nativeRenderer, component, atom, context, needMove) {
1424
- const diffAtom = atom.child;
1425
- component.update(component.props, newTemplate => {
1426
- atom.child = createChildChain(newTemplate, atom.namespace);
1427
- diff(nativeRenderer, component, atom.child, diffAtom, context, needMove);
1428
- const next = atom.sibling;
1429
- if (next && next.jsxNode instanceof Component) {
1430
- const view = componentViewCache.get(next.jsxNode);
1431
- view.host = context.host;
1432
- view.isParent = context.isParent;
1433
- }
1434
- }, (skipSubComponentDiff) => {
1435
- reuseComponentView(nativeRenderer, atom, context, needMove, skipSubComponentDiff);
1436
- });
1437
- }
1438
1352
  function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, needMove) {
1439
1353
  const commits = [];
1440
1354
  function changeOffset() {
@@ -1450,7 +1364,8 @@ function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, needMo
1450
1364
  dirtyDiffAtom = dirtyDiffAtom.sibling;
1451
1365
  }
1452
1366
  let offset = 0;
1453
- for (let i = 0; i < commits.length; i++) {
1367
+ const len = commits.length;
1368
+ for (let i = 0; i < len; i++) {
1454
1369
  const commit = commits[i];
1455
1370
  while (oldAtom) {
1456
1371
  if (oldAtom.index <= i) {
@@ -1460,7 +1375,7 @@ function diff(nativeRenderer, parentComponent, newAtom, oldAtom, context, needMo
1460
1375
  }
1461
1376
  break;
1462
1377
  }
1463
- commit(offset, needMove);
1378
+ commit.callback(commit.params, offset, needMove);
1464
1379
  }
1465
1380
  }
1466
1381
  function createChanges(newAtom, oldAtom, nativeRenderer, commits, context, parentComponent, effect) {
@@ -1469,17 +1384,19 @@ function createChanges(newAtom, oldAtom, nativeRenderer, commits, context, paren
1469
1384
  while (oldAtom) {
1470
1385
  const newAtomType = newAtom.type;
1471
1386
  if (oldAtom.type === newAtomType && oldAtom.nodeType === newAtom.nodeType && oldAtom.key === newAtom.key) {
1472
- let commit;
1473
- if (newAtomType === TextAtomType) {
1474
- commit = updateText(newAtom, oldAtom, nativeRenderer, context);
1475
- }
1476
- else if (newAtomType === ComponentAtomType) {
1477
- commit = updateComponent(newAtom, oldAtom, nativeRenderer, context);
1478
- }
1479
- else {
1480
- commit = updateElement(newAtom, oldAtom, nativeRenderer, context, parentComponent);
1481
- }
1482
- commits.push(commit);
1387
+ commits.push({
1388
+ callback: newAtomType === TextAtomType ? updateText :
1389
+ newAtomType === ComponentAtomType ? updateComponent :
1390
+ updateElement,
1391
+ params: {
1392
+ oldAtom,
1393
+ newAtom,
1394
+ nativeRenderer,
1395
+ context,
1396
+ effect,
1397
+ parentComponent
1398
+ }
1399
+ });
1483
1400
  const next = oldAtom.sibling;
1484
1401
  if (!prev) {
1485
1402
  return next;
@@ -1490,81 +1407,85 @@ function createChanges(newAtom, oldAtom, nativeRenderer, commits, context, paren
1490
1407
  prev = oldAtom;
1491
1408
  oldAtom = oldAtom.sibling;
1492
1409
  }
1493
- commits.push(createNewView(newAtom, nativeRenderer, context, parentComponent, effect));
1410
+ commits.push({
1411
+ callback: patchUpdate,
1412
+ params: {
1413
+ oldAtom: oldAtom,
1414
+ newAtom,
1415
+ nativeRenderer,
1416
+ context,
1417
+ effect,
1418
+ parentComponent
1419
+ }
1420
+ });
1494
1421
  return startDiffAtom;
1495
1422
  }
1496
- function createNewView(start, nativeRenderer, context, parentComponent, effect) {
1497
- return function () {
1498
- buildView(nativeRenderer, parentComponent, start, context);
1499
- effect();
1500
- };
1423
+ function patchUpdate(params) {
1424
+ const { nativeRenderer, parentComponent, newAtom, context, effect } = params;
1425
+ buildView(nativeRenderer, parentComponent, newAtom, context);
1426
+ effect();
1501
1427
  }
1502
- function updateText(newAtom, oldAtom, nativeRenderer, context) {
1503
- return function (offset, needMove) {
1504
- const nativeNode = oldAtom.nativeNode;
1505
- newAtom.nativeNode = nativeNode;
1506
- if (needMove || newAtom.index - offset !== oldAtom.index) {
1507
- insertNode(nativeRenderer, newAtom, context);
1508
- }
1509
- context.host = nativeNode;
1510
- context.isParent = false;
1511
- };
1428
+ function updateText(params, offset, needMove) {
1429
+ const { oldAtom, newAtom, nativeRenderer, context } = params;
1430
+ const nativeNode = oldAtom.nativeNode;
1431
+ newAtom.nativeNode = nativeNode;
1432
+ if (needMove || newAtom.index - offset !== oldAtom.index) {
1433
+ insertNode(nativeRenderer, newAtom, context);
1434
+ }
1435
+ context.host = nativeNode;
1436
+ context.isParent = false;
1512
1437
  }
1513
- function updateElement(newAtom, oldAtom, nativeRenderer, context, parentComponent) {
1514
- return function (offset, needMove) {
1515
- newAtom.nativeNode = oldAtom.nativeNode;
1516
- if (needMove || newAtom.index - offset !== oldAtom.index) {
1517
- insertNode(nativeRenderer, newAtom, context);
1518
- }
1519
- context.host = newAtom.nativeNode;
1520
- context.isParent = false;
1521
- updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComponent, {
1522
- host: newAtom.nativeNode,
1523
- isParent: true,
1524
- rootHost: context.rootHost
1525
- });
1526
- };
1438
+ function updateElement(params, offset, needMove) {
1439
+ const { nativeRenderer, newAtom, oldAtom, context, parentComponent } = params;
1440
+ newAtom.nativeNode = oldAtom.nativeNode;
1441
+ if (needMove || newAtom.index - offset !== oldAtom.index) {
1442
+ insertNode(nativeRenderer, newAtom, context);
1443
+ }
1444
+ context.host = newAtom.nativeNode;
1445
+ context.isParent = false;
1446
+ updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComponent, {
1447
+ host: newAtom.nativeNode,
1448
+ isParent: true,
1449
+ rootHost: context.rootHost
1450
+ });
1527
1451
  }
1528
- function updateComponent(newAtom, reusedAtom, nativeRenderer, context) {
1529
- return function (offset, needMove) {
1530
- const component = reusedAtom.jsxNode;
1531
- const newProps = newAtom.jsxNode.props;
1532
- const portalHost = component.instance.$portalHost;
1533
- context = portalHost ? { isParent: true, host: portalHost, rootHost: portalHost } : context;
1534
- componentViewCache.set(component, Object.assign({ atom: newAtom }, context));
1535
- newAtom.jsxNode = component;
1536
- component.update(newProps, newTemplate => {
1537
- if (newTemplate) {
1538
- newAtom.child = createChildChain(newTemplate, newAtom.namespace);
1539
- }
1540
- if (newAtom.child) {
1541
- diff(nativeRenderer, component, newAtom.child, reusedAtom.child, context, needMove || newAtom.index - offset !== reusedAtom.index);
1542
- }
1543
- else if (reusedAtom.child) {
1544
- let atom = reusedAtom.child;
1545
- while (atom) {
1546
- cleanView(nativeRenderer, atom, true);
1547
- atom = atom.sibling;
1548
- }
1549
- }
1550
- }, (skipSubComponentDiff) => {
1551
- newAtom.child = reusedAtom.child;
1552
- reuseComponentView(nativeRenderer, newAtom.child, context, needMove || newAtom.index - offset !== reusedAtom.index, skipSubComponentDiff);
1553
- });
1554
- };
1452
+ function updateComponent(params, offset, needMove) {
1453
+ const { oldAtom, newAtom, nativeRenderer } = params;
1454
+ let context = params.context;
1455
+ const component = oldAtom.jsxNode;
1456
+ const portalHost = component.instance.$portalHost;
1457
+ context = portalHost ? { isParent: true, host: portalHost, rootHost: portalHost } : context;
1458
+ component.viewMetadata = Object.assign({ atom: newAtom }, context);
1459
+ const newProps = newAtom.jsxNode.props;
1460
+ newAtom.jsxNode = component;
1461
+ needMove = needMove || newAtom.index - offset !== oldAtom.index;
1462
+ const canUpdate = component.canUpdate(component.props, newProps);
1463
+ const propsIsChanged = hasChange(newProps, component.props);
1464
+ if (propsIsChanged) {
1465
+ component.updateProps(newProps);
1466
+ }
1467
+ if (canUpdate && (propsIsChanged || component.dirty)) {
1468
+ patchComponent(nativeRenderer, component, oldAtom.child, newAtom, context, needMove);
1469
+ const next = oldAtom.sibling;
1470
+ if (next && next.jsxNode instanceof Component) {
1471
+ const view = next.jsxNode.viewMetadata;
1472
+ view.host = context.host;
1473
+ view.isParent = context.isParent;
1474
+ }
1475
+ }
1476
+ else {
1477
+ newAtom.child = oldAtom.child;
1478
+ reuseComponentView(nativeRenderer, newAtom.child, context, needMove, !canUpdate);
1479
+ }
1480
+ component.rendered();
1555
1481
  }
1556
1482
  function reuseComponentView(nativeRenderer, child, context, moveView, skipSubComponentDiff) {
1557
1483
  const updateContext = (atom) => {
1558
- if (atom.jsxNode instanceof Component) {
1559
- if (skipSubComponentDiff || !moveView) {
1560
- let child = atom.child;
1561
- while (child) {
1562
- updateContext(child);
1563
- child = child.sibling;
1564
- }
1565
- }
1566
- else {
1567
- applyChanges(nativeRenderer, atom.jsxNode, atom, context, true);
1484
+ const jsxNode = atom.jsxNode;
1485
+ if (jsxNode instanceof Component) {
1486
+ reuseComponentView(nativeRenderer, atom.child, context, moveView, skipSubComponentDiff);
1487
+ if (!skipSubComponentDiff) {
1488
+ deepUpdateByComponentDirtyTree(nativeRenderer, jsxNode, moveView);
1568
1489
  }
1569
1490
  }
1570
1491
  else {
@@ -1585,7 +1506,7 @@ function reuseElementChildrenView(nativeRenderer, atom, context, skipSubComponen
1585
1506
  let child = atom.child;
1586
1507
  while (child) {
1587
1508
  if (child.jsxNode instanceof Component) {
1588
- updateView(nativeRenderer, child.jsxNode, false);
1509
+ deepUpdateByComponentDirtyTree(nativeRenderer, child.jsxNode, false);
1589
1510
  }
1590
1511
  else {
1591
1512
  reuseElementChildrenView(nativeRenderer, child);
@@ -1632,7 +1553,7 @@ function componentRender(nativeRenderer, component, from, context) {
1632
1553
  component.render((template, portalHost) => {
1633
1554
  from.child = createChildChain(template, from.namespace);
1634
1555
  context = portalHost ? { isParent: true, host: portalHost, rootHost: portalHost } : context;
1635
- componentViewCache.set(component, Object.assign({ atom: from }, context));
1556
+ component.viewMetadata = Object.assign({ atom: from }, context);
1636
1557
  let child = from.child;
1637
1558
  while (child) {
1638
1559
  buildView(nativeRenderer, component, child, context);
@@ -1657,14 +1578,14 @@ function createChainByJSXNode(type, jsxNode, nodeType, prevAtom, namespace, key)
1657
1578
  }
1658
1579
  function createChainByNode(jsxNode, prevAtom, elementNamespace) {
1659
1580
  const type = typeof jsxNode;
1660
- if (jsxNode !== null && type !== 'undefined' && type !== 'boolean') {
1661
- if (typeof jsxNode === 'string') {
1581
+ if (jsxNode != null && type !== 'boolean') {
1582
+ if (type === 'string') {
1662
1583
  return createChainByJSXNode(TextAtomType, jsxNode, jsxNode, prevAtom, elementNamespace);
1663
1584
  }
1664
- if (Array.isArray(jsxNode)) {
1665
- return createChainByChildren(jsxNode, prevAtom, elementNamespace);
1666
- }
1667
1585
  if (type === 'object') {
1586
+ if (Array.isArray(jsxNode)) {
1587
+ return createChainByChildren(jsxNode, prevAtom, elementNamespace);
1588
+ }
1668
1589
  const nodeType = typeof jsxNode.type;
1669
1590
  if (nodeType === 'string') {
1670
1591
  return createChainByJSXNode(ElementAtomType, jsxNode, jsxNode.type, prevAtom, elementNamespace || ElementNamespaceMap[jsxNode.type], jsxNode.key);
@@ -1775,43 +1696,66 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
1775
1696
  reuseElementChildrenView(nativeRenderer, newAtom);
1776
1697
  return;
1777
1698
  }
1778
- const changes = getObjectChanges(newVNode.props, oldVNode.props);
1779
1699
  let unBindRefs;
1780
1700
  let bindRefs;
1781
1701
  let updatedChildren = false;
1782
- let len = changes.remove.length;
1783
- for (let i = 0; i < len; i++) {
1784
- const [key, value] = changes.remove[i];
1702
+ comparePropsWithCallbacks(oldVNode.props, newVNode.props, (key, oldValue) => {
1785
1703
  if (key === 'children') {
1786
1704
  updatedChildren = true;
1787
1705
  cleanElementChildren(oldAtom, nativeRenderer);
1788
- continue;
1706
+ return;
1789
1707
  }
1790
1708
  if (key === 'class') {
1791
1709
  nativeRenderer.setClass(nativeNode, '', isSvg);
1792
- continue;
1710
+ return;
1793
1711
  }
1794
1712
  if (key === 'style') {
1795
- for (const styleName in styleToObject(value)) {
1713
+ for (const styleName in styleToObject(oldValue)) {
1796
1714
  nativeRenderer.removeStyle(nativeNode, styleName, isSvg);
1797
1715
  }
1798
- continue;
1716
+ return;
1799
1717
  }
1800
1718
  if (listenerReg.test(key)) {
1801
- if (typeof value === 'function') {
1802
- nativeRenderer.unListen(nativeNode, key, value, isSvg);
1719
+ if (typeof oldValue === 'function') {
1720
+ nativeRenderer.unListen(nativeNode, key, oldValue, isSvg);
1803
1721
  }
1804
- continue;
1722
+ return;
1805
1723
  }
1806
1724
  if (key === refKey) {
1807
- unBindRefs = value;
1808
- continue;
1725
+ unBindRefs = oldValue;
1726
+ return;
1809
1727
  }
1810
1728
  nativeRenderer.removeProperty(nativeNode, key, isSvg);
1811
- }
1812
- len = changes.replace.length;
1813
- for (let i = 0; i < len; i++) {
1814
- const [key, newValue, oldValue] = changes.replace[i];
1729
+ }, (key, value) => {
1730
+ if (key === 'children') {
1731
+ updatedChildren = true;
1732
+ newAtom.child = createElementChildren(newVNode.type, value, isSvg);
1733
+ buildElementChildren(newAtom, nativeRenderer, parentComponent, context);
1734
+ return;
1735
+ }
1736
+ if (key === 'class') {
1737
+ nativeRenderer.setClass(nativeNode, classToString(value), isSvg);
1738
+ return;
1739
+ }
1740
+ if (key === 'style') {
1741
+ const styleObj = styleToObject(value);
1742
+ for (const styleName in styleObj) {
1743
+ nativeRenderer.setStyle(nativeNode, styleName, styleObj[styleName], isSvg);
1744
+ }
1745
+ return;
1746
+ }
1747
+ if (listenerReg.test(key)) {
1748
+ if (typeof value === 'function') {
1749
+ nativeRenderer.listen(nativeNode, key, value, isSvg);
1750
+ }
1751
+ return;
1752
+ }
1753
+ if (key === refKey) {
1754
+ bindRefs = value;
1755
+ return;
1756
+ }
1757
+ nativeRenderer.setProperty(nativeNode, key, value, isSvg);
1758
+ }, (key, newValue, oldValue) => {
1815
1759
  if (key === 'children') {
1816
1760
  updatedChildren = true;
1817
1761
  newAtom.child = createElementChildren(newVNode.type, newValue, isSvg);
@@ -1824,7 +1768,7 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
1824
1768
  else {
1825
1769
  diff(nativeRenderer, parentComponent, newAtom.child, oldAtom.child, context, false);
1826
1770
  }
1827
- continue;
1771
+ return;
1828
1772
  }
1829
1773
  if (key === 'class') {
1830
1774
  const oldClassName = classToString(oldValue);
@@ -1832,62 +1776,30 @@ function updateNativeNodeProperties(nativeRenderer, newAtom, oldAtom, parentComp
1832
1776
  if (oldClassName !== newClassName) {
1833
1777
  nativeRenderer.setClass(nativeNode, newClassName, isSvg);
1834
1778
  }
1835
- continue;
1779
+ return;
1836
1780
  }
1837
1781
  if (key === 'style') {
1838
- const styleChanges = getObjectChanges(styleToObject(newValue) || {}, styleToObject(oldValue) || {});
1839
- for (const [styleName] of styleChanges.remove) {
1782
+ comparePropsWithCallbacks(styleToObject(oldValue), styleToObject(newValue), styleName => {
1840
1783
  nativeRenderer.removeStyle(nativeNode, styleName, isSvg);
1841
- }
1842
- for (const [styleName, styleValue] of [...styleChanges.add, ...styleChanges.replace]) {
1784
+ }, (styleName, styleValue) => {
1843
1785
  nativeRenderer.setStyle(nativeNode, styleName, styleValue, isSvg);
1844
- }
1845
- continue;
1786
+ }, (styleName, styleValue) => {
1787
+ nativeRenderer.setStyle(nativeNode, styleName, styleValue, isSvg);
1788
+ });
1789
+ return;
1846
1790
  }
1847
1791
  if (listenerReg.test(key)) {
1848
1792
  nativeRenderer.unListen(nativeNode, key, oldValue, isSvg);
1849
1793
  nativeRenderer.listen(nativeNode, key, newValue, isSvg);
1850
- continue;
1794
+ return;
1851
1795
  }
1852
1796
  if (key === refKey) {
1853
1797
  unBindRefs = oldValue;
1854
1798
  bindRefs = newValue;
1855
- continue;
1799
+ return;
1856
1800
  }
1857
1801
  nativeRenderer.setProperty(nativeNode, key, newValue, isSvg);
1858
- }
1859
- len = changes.add.length;
1860
- for (let i = 0; i < len; i++) {
1861
- const [key, value] = changes.add[i];
1862
- if (key === 'children') {
1863
- updatedChildren = true;
1864
- newAtom.child = createElementChildren(newVNode.type, value, isSvg);
1865
- buildElementChildren(newAtom, nativeRenderer, parentComponent, context);
1866
- continue;
1867
- }
1868
- if (key === 'class') {
1869
- nativeRenderer.setClass(nativeNode, classToString(value), isSvg);
1870
- continue;
1871
- }
1872
- if (key === 'style') {
1873
- const styleObj = styleToObject(value);
1874
- for (const styleName in styleObj) {
1875
- nativeRenderer.setStyle(nativeNode, styleName, styleObj[styleName], isSvg);
1876
- }
1877
- continue;
1878
- }
1879
- if (listenerReg.test(key)) {
1880
- if (typeof value === 'function') {
1881
- nativeRenderer.listen(nativeNode, key, value, isSvg);
1882
- }
1883
- continue;
1884
- }
1885
- if (key === refKey) {
1886
- bindRefs = value;
1887
- continue;
1888
- }
1889
- nativeRenderer.setProperty(nativeNode, key, value, isSvg);
1890
- }
1802
+ });
1891
1803
  if (!updatedChildren) {
1892
1804
  newAtom.child = oldAtom.child;
1893
1805
  reuseElementChildrenView(nativeRenderer, newAtom);