Skip to content

Commit a9d4bd8

Browse files
author
Brian Vaughn
committed
DevTools: Named hooks supports 'cheap-module-source-map'
This is the default used in created-react-dev mode. These source maps don't support column numbers, so DevTools needs to be more lenient when matching AST nodes in this mode.
1 parent 9fec3f2 commit a9d4bd8

File tree

2 files changed

+49
-27
lines changed

2 files changed

+49
-27
lines changed

packages/react-devtools-extensions/src/astUtils.js

Lines changed: 48 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -32,30 +32,32 @@ const AST_NODE_TYPES = Object.freeze({
3232
function checkNodeLocation(
3333
path: NodePath,
3434
line: number,
35-
column: number,
35+
column?: number | null = null,
3636
): boolean {
3737
const {start, end} = path.node.loc;
3838

3939
if (line < start.line || line > end.line) {
4040
return false;
4141
}
4242

43-
// Column numbers are representated differently between tools/engines.
44-
// Error.prototype.stack columns are 1-based (like most IDEs) but ASTs are 0-based.
45-
//
46-
// In practice this will probably never matter,
47-
// because this code matches the 1-based Error stack location for the hook Identifier (e.g. useState)
48-
// with the larger 0-based VariableDeclarator (e.g. [foo, setFoo] = useState())
49-
// so the ranges should always overlap.
50-
//
51-
// For more info see https://github.com/facebook/react/pull/21833#discussion_r666831276
52-
column -= 1;
53-
54-
if (
55-
(line === start.line && column < start.column) ||
56-
(line === end.line && column > end.column)
57-
) {
58-
return false;
43+
if (column !== null) {
44+
// Column numbers are representated differently between tools/engines.
45+
// Error.prototype.stack columns are 1-based (like most IDEs) but ASTs are 0-based.
46+
//
47+
// In practice this will probably never matter,
48+
// because this code matches the 1-based Error stack location for the hook Identifier (e.g. useState)
49+
// with the larger 0-based VariableDeclarator (e.g. [foo, setFoo] = useState())
50+
// so the ranges should always overlap.
51+
//
52+
// For more info see https://github.com/facebook/react/pull/21833#discussion_r666831276
53+
column -= 1;
54+
55+
if (
56+
(line === start.line && column < start.column) ||
57+
(line === end.line && column > end.column)
58+
) {
59+
return false;
60+
}
5961
}
6062

6163
return true;
@@ -122,15 +124,35 @@ export function getHookName(
122124
): string | null {
123125
const hooksFromAST = getPotentialHookDeclarationsFromAST(originalSourceAST);
124126

125-
const potentialReactHookASTNode = hooksFromAST.find(node => {
126-
const nodeLocationCheck = checkNodeLocation(
127-
node,
128-
originalSourceLineNumber,
129-
originalSourceColumnNumber,
130-
);
131-
const hookDeclaractionCheck = isConfirmedHookDeclaration(node);
132-
return nodeLocationCheck && hookDeclaractionCheck;
133-
});
127+
let potentialReactHookASTNode = null;
128+
if (originalSourceColumnNumber === 0) {
129+
// This most likely indicates a source map type like 'cheap-module-source-map'
130+
// that intentionally drops column numbers for compilation speed in DEV builds.
131+
// In this case, we can assume there's probably only one hook per line (true in most cases)
132+
// and just fail if we find more than one match.
133+
const matchingNodes = hooksFromAST.filter(node => {
134+
const nodeLocationCheck = checkNodeLocation(
135+
node,
136+
originalSourceLineNumber,
137+
);
138+
const hookDeclaractionCheck = isConfirmedHookDeclaration(node);
139+
return nodeLocationCheck && hookDeclaractionCheck;
140+
});
141+
142+
if (matchingNodes.length === 1) {
143+
potentialReactHookASTNode = matchingNodes[0];
144+
}
145+
} else {
146+
potentialReactHookASTNode = hooksFromAST.find(node => {
147+
const nodeLocationCheck = checkNodeLocation(
148+
node,
149+
originalSourceLineNumber,
150+
originalSourceColumnNumber,
151+
);
152+
const hookDeclaractionCheck = isConfirmedHookDeclaration(node);
153+
return nodeLocationCheck && hookDeclaractionCheck;
154+
});
155+
}
134156

135157
if (!potentialReactHookASTNode) {
136158
return null;

packages/react-devtools-extensions/src/parseHookNames.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ function fetchFile(url: string): Promise<string> {
350350
},
351351
error => {
352352
if (__DEBUG__) {
353-
console.log(`fetchFile() Could not fetch file "${error.message}"`);
353+
console.log(`fetchFile() Could not fetch file: ${error.message}`);
354354
}
355355
reject(null);
356356
},

0 commit comments

Comments
 (0)