Skip to content

Commit a1c5c31

Browse files
committed
fix: false negative comparisons with react-hot-dom enabled, fixes #1299
1 parent 0d665c8 commit a1c5c31

File tree

3 files changed

+40
-29
lines changed

3 files changed

+40
-29
lines changed

.prettierignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ babel.js
99
index.js
1010
patch.js
1111
root.js
12-
test/hot/react-dom
12+
test/hot/react-dom
13+
coverage

src/reconciler/componentComparator.js

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -182,41 +182,45 @@ const compareComponents = (oldType, newType, setNewType, baseType) => {
182182
const knownPairs = new WeakMap();
183183
const emptyMap = new WeakMap();
184184

185+
const getKnownPair = (oldType, newType) => {
186+
const pair = knownPairs.get(oldType) || emptyMap;
187+
return pair.get(newType);
188+
};
189+
185190
export const hotComponentCompare = (oldType, preNewType, setNewType, baseType) => {
186191
const hotActive = hotComparisonOpen();
187192
const newType = configuration.integratedResolver ? resolveType(preNewType) : preNewType;
188-
let result = oldType === newType;
189193

190-
if (!hotActive) {
191-
return result;
192-
}
194+
// TODO: find out the root cause
195+
// we could not use "fast result" here - go a full part to update a fiber.
196+
// const knownType = getKnownPair(oldType, newType);
197+
// if (knownType !== undefined) {
198+
// return knownType;
199+
// }
193200

194-
if (
195-
!isReloadableComponent(oldType) ||
196-
!isReloadableComponent(newType) ||
197-
isColdType(oldType) ||
198-
isColdType(oldType) ||
199-
!oldType ||
200-
!newType ||
201-
0
202-
) {
203-
return result;
204-
}
201+
let result = oldType === newType;
205202

206-
// comparison should be active only if hot update window
207-
// or it would merge components it shall not
208203
if (hotActive) {
204+
// pre fail components which could not be merged
205+
if (
206+
!isReloadableComponent(oldType) ||
207+
!isReloadableComponent(newType) ||
208+
isColdType(oldType) ||
209+
isColdType(oldType) ||
210+
!oldType ||
211+
!newType ||
212+
0
213+
) {
214+
return result;
215+
}
216+
209217
result = compareComponents(oldType, newType, setNewType, baseType);
210218
const pair = knownPairs.get(oldType) || new WeakMap();
211219
pair.set(newType, result);
212220
knownPairs.set(oldType, pair);
213221
return result;
214222
}
215223

216-
if (result) {
217-
return result;
218-
}
219-
220-
const pair = knownPairs.get(oldType) || emptyMap;
221-
return pair.get(newType) || false;
224+
// result - true if components are equal, or were "equal" at any point in the past
225+
return result || getKnownPair(oldType, newType) || false;
222226
};

src/reconciler/resolver.js

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,23 @@ import configuration, { internalConfiguration } from '../configuration';
1212
const shouldNotPatchComponent = type => isTypeBlacklisted(type);
1313

1414
export function resolveType(type, options = {}) {
15-
const element = { type };
16-
if (isLazyType(element) || isMemoType(element) || isForwardType(element) || isContextType(element)) {
17-
return getProxyByType(type) || type;
18-
}
19-
15+
// fast return
2016
if (!isCompositeComponent(type) || isProxyType(type)) {
2117
return type;
2218
}
2319

20+
const element = { type };
21+
22+
// fast meta
23+
if (typeof element === 'object') {
24+
if (isLazyType(element) || isMemoType(element) || isForwardType(element) || isContextType(element)) {
25+
return getProxyByType(type) || type;
26+
}
27+
}
28+
2429
const existingProxy = getProxyByType(type);
2530

31+
// cold API
2632
if (shouldNotPatchComponent(type)) {
2733
return existingProxy ? existingProxy.getCurrent() : type;
2834
}

0 commit comments

Comments
 (0)