Skip to content

Commit 1b9f2da

Browse files
committed
fix: make type comparison stronger
1 parent 045a27f commit 1b9f2da

File tree

2 files changed

+63
-22
lines changed

2 files changed

+63
-22
lines changed

src/internal/reactUtils.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,34 @@ export const isForwardType = ({ type }) =>
6666
type && typeof type === 'object' && '$$typeof' in type && type.$$typeof === ForwardType && ForwardType;
6767
export const isContextType = type => isContextConsumer(type) || isContextProvider(type);
6868

69+
export const getElementType = type => {
70+
const element = { type };
71+
72+
if (isContextConsumer(element)) {
73+
return 'Consumer';
74+
}
75+
if (isContextProvider(element)) {
76+
return 'Provider';
77+
}
78+
if (isLazyType(element)) {
79+
return 'Lazy';
80+
}
81+
if (isMemoType(element)) {
82+
return 'Memo';
83+
}
84+
if (isForwardType(element)) {
85+
return 'Forward';
86+
}
87+
88+
if (isReactClass(type)) {
89+
return 'Class';
90+
}
91+
92+
if (typeof element === 'function') {
93+
return 'FC';
94+
}
95+
96+
return 'unknown';
97+
};
98+
6999
export const getContextProvider = type => type && type._context;

src/reconciler/componentComparator.js

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { getIdByType, getProxyByType, getSignature, isColdType, updateProxyById } from './proxies';
22
import { hotComparisonOpen } from '../global/generation';
33
import {
4+
getElementType,
45
isContextType,
56
isForwardType,
67
isLazyType,
@@ -20,31 +21,36 @@ const getInnerComponentType = component => {
2021
};
2122

2223
function haveEqualSignatures(prevType, nextType) {
23-
const prevSignature = getSignature(prevType);
24-
const nextSignature = getSignature(nextType);
24+
try {
25+
const prevSignature = getSignature(prevType);
26+
const nextSignature = getSignature(nextType);
2527

26-
if (prevSignature === undefined && nextSignature === undefined) {
27-
return true;
28-
}
29-
if (prevSignature === undefined || nextSignature === undefined) {
30-
return false;
31-
}
32-
if (prevSignature.key !== nextSignature.key) {
33-
return false;
34-
}
35-
36-
// TODO: we might need to calculate previous signature earlier in practice,
37-
// such as during the first time a component is resolved. We'll revisit this.
38-
const prevCustomHooks = prevSignature.getCustomHooks();
39-
const nextCustomHooks = nextSignature.getCustomHooks();
40-
if (prevCustomHooks.length !== nextCustomHooks.length) {
41-
return false;
42-
}
28+
if (prevSignature === undefined && nextSignature === undefined) {
29+
return true;
30+
}
31+
if (prevSignature === undefined || nextSignature === undefined) {
32+
return false;
33+
}
34+
if (prevSignature.key !== nextSignature.key) {
35+
return false;
36+
}
4337

44-
for (let i = 0; i < nextCustomHooks.length; i++) {
45-
if (!haveEqualSignatures(prevCustomHooks[i], nextCustomHooks[i])) {
38+
// TODO: we might need to calculate previous signature earlier in practice,
39+
// such as during the first time a component is resolved. We'll revisit this.
40+
const prevCustomHooks = prevSignature.getCustomHooks();
41+
const nextCustomHooks = nextSignature.getCustomHooks();
42+
if (prevCustomHooks.length !== nextCustomHooks.length) {
4643
return false;
4744
}
45+
46+
for (let i = 0; i < nextCustomHooks.length; i++) {
47+
if (!haveEqualSignatures(prevCustomHooks[i], nextCustomHooks[i])) {
48+
return false;
49+
}
50+
}
51+
} catch (e) {
52+
logger.error('React-Hot-Loader: error occurred while comparing hook signature', e);
53+
return false;
4854
}
4955

5056
return true;
@@ -99,7 +105,12 @@ const areDeepSwappable = (oldType, newType) => {
99105
const compareComponents = (oldType, newType, setNewType, baseType) => {
100106
let defaultResult = oldType === newType;
101107

102-
if ((oldType && !newType) || (!oldType && newType) || typeof oldType !== typeof newType) {
108+
if (
109+
(oldType && !newType) ||
110+
(!oldType && newType) ||
111+
typeof oldType !== typeof newType ||
112+
getElementType(oldType) !== getElementType(newType)
113+
) {
103114
return defaultResult;
104115
}
105116

0 commit comments

Comments
 (0)