DevTools: Update named hooks match to use column number also (#21833)
This prevents edge cases where AST nodes are incorrectly matched.
Brian Vaughn committed
Jul 8, 2021 at 16:12 UTC
f52b73f9d0a9adbdb2815af440b2edd6b5627ff0
24 files changed
+324
-76
.eslintignore
+1
@@ -21,6 +21,7 @@ packages/react-devtools-extensions/chrome/build
21
packages/react-devtools-extensions/firefox/build
22
packages/react-devtools-extensions/shared/build
23
packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/
24
+packages/react-devtools-extensions/src/__tests__/__source__/__untransformed__/
25
packages/react-devtools-extensions/src/ErrorTesterCompiled.js
26
packages/react-devtools-inline/dist
27
packages/react-devtools-shell/dist
.prettierignore
+1
@@ -3,6 +3,7 @@ packages/react-devtools-extensions/chrome/build
3
packages/react-devtools-extensions/firefox/build
4
packages/react-devtools-extensions/shared/build
5
packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/
6
+packages/react-devtools-extensions/src/__tests__/__source__/__untransformed__/
7
packages/react-devtools-extensions/src/ErrorTesterCompiled.js
8
packages/react-devtools-inline/dist
9
packages/react-devtools-shell/dist
packages/react-devtools-extensions/src/__tests__/__source__/ComponentWithMultipleHooksPerLine.js
new
+23
@@ -0,0 +1,23 @@
1
+/**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow
8
+ */
9
+
10
+import {createContext, useContext} from 'react';
11
+
12
+const A = createContext(1);
13
+const B = createContext(2);
14
+
15
+export function Component() {
16
+ const a = useContext(A);
17
+ const b = useContext(B);
18
+
19
+ // prettier-ignore
20
+ const c = useContext(A), d = useContext(B); // eslint-disable-line one-var
21
+
22
+ return a + b + c + d;
23
+}
packages/react-devtools-extensions/src/__tests__/__source__/README.md
renamed
packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/bundle/index.js
+24
-3
@@ -71,7 +71,27 @@ function Component$1() {
71
*
72
* @flow
73
*/
74
+const A = /*#__PURE__*/React.createContext(1);
75
+const B = /*#__PURE__*/React.createContext(2);
76
function Component$2() {
77
+ const a = React.useContext(A);
78
+ const b = React.useContext(B); // prettier-ignore
79
+
80
+ const c = React.useContext(A),
81
+ d = React.useContext(B); // eslint-disable-line one-var
82
+
83
+ return a + b + c + d;
84
+}
85
+
86
+/**
87
+ * Copyright (c) Facebook, Inc. and its affiliates.
88
+ *
89
+ * This source code is licensed under the MIT license found in the
90
+ * LICENSE file in the root directory of this source tree.
91
+ *
92
+ * @flow
93
+ */
94
+function Component$3() {
95
const [count, setCount] = React.useState(0);
96
return /*#__PURE__*/React__default.createElement("div", null, /*#__PURE__*/React__default.createElement("p", null, "You clicked ", count, " times"), /*#__PURE__*/React__default.createElement("button", {
97
onClick: () => setCount(count + 1)
@@ -86,7 +106,7 @@ function Component$2() {
106
*
107
* @flow
108
*/
89
-function Component$3() {
109
+function Component$4() {
110
const [count] = require('react').useState(0);
111
112
return count;
@@ -191,8 +211,9 @@ var ToDoList = /*#__PURE__*/Object.freeze({
211
212
exports.ComponentWithCustomHook = Component;
213
exports.ComponentWithExternalCustomHooks = Component$1;
194
-exports.Example = Component$2;
195
-exports.InlineRequire = Component$3;
214
+exports.ComponentWithMultipleHooksPerLine = Component$2;
215
+exports.Example = Component$3;
216
+exports.InlineRequire = Component$4;
217
exports.ToDoList = ToDoList;
218
exports.useTheme = useTheme;
219
//# sourceMappingURL=index.js.map
packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/bundle/index.js.map
+1
-1
@@ -1 +1 @@
1
-{"version":3,"file":"index.js","sources":["../../ComponentWithCustomHook.js","../../useTheme.js","../../ComponentWithExternalCustomHooks.js","../../Example.js","../../InlineRequire.js","../../ToDoList.js"],"sourcesContent":["/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport React, {useEffect, useState} from 'react';\n\nexport function Component() {\n const [count, setCount] = useState(0);\n const isDarkMode = useIsDarkMode();\n\n useEffect(() => {\n // ...\n }, []);\n\n const handleClick = () => setCount(count + 1);\n\n return (\n <>\n <div>Dark mode? {isDarkMode}</div>\n <div>Count: {count}</div>\n <button onClick={handleClick}>Update count</button>\n </>\n );\n}\n\nfunction useIsDarkMode() {\n const [isDarkMode] = useState(false);\n\n useEffect(function useEffectCreate() {\n // Here is where we may listen to a \"theme\" event...\n }, []);\n\n return isDarkMode;\n}\n","/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {createContext, useContext, useDebugValue} from 'react';\n\nexport const ThemeContext = createContext('bright');\n\nexport default function useTheme() {\n const theme = useContext(ThemeContext);\n useDebugValue(theme);\n return theme;\n}\n","/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport React from 'react';\nimport useTheme from './useTheme';\n\nexport function Component() {\n const theme = useTheme();\n\n return <div>theme: {theme}</div>;\n}\n","/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport React, {useState} from 'react';\n\nexport function Component() {\n const [count, setCount] = useState(0);\n\n return (\n <div>\n <p>You clicked {count} times</p>\n <button onClick={() => setCount(count + 1)}>Click me</button>\n </div>\n );\n}\n","/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport function Component() {\n const [count] = require('react').useState(0);\n\n return count;\n}\n","/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {Fragment, useCallback, useState} from 'react';\n\nexport function ListItem({item, removeItem, toggleItem}) {\n const handleDelete = useCallback(() => {\n removeItem(item);\n }, [item, removeItem]);\n\n const handleToggle = useCallback(() => {\n toggleItem(item);\n }, [item, toggleItem]);\n\n return (\n <li>\n <button onClick={handleDelete}>Delete</button>\n <label>\n <input\n checked={item.isComplete}\n onChange={handleToggle}\n type=\"checkbox\"\n />{' '}\n {item.text}\n </label>\n </li>\n );\n}\n\nexport function List(props) {\n const [newItemText, setNewItemText] = useState('');\n const [items, setItems] = useState([\n {id: 1, isComplete: true, text: 'First'},\n {id: 2, isComplete: true, text: 'Second'},\n {id: 3, isComplete: false, text: 'Third'},\n ]);\n const [uid, setUID] = useState(4);\n\n const handleClick = useCallback(() => {\n if (newItemText !== '') {\n setItems([\n ...items,\n {\n id: uid,\n isComplete: false,\n text: newItemText,\n },\n ]);\n setUID(uid + 1);\n setNewItemText('');\n }\n }, [newItemText, items, uid]);\n\n const handleKeyPress = useCallback(\n event => {\n if (event.key === 'Enter') {\n handleClick();\n }\n },\n [handleClick],\n );\n\n const handleChange = useCallback(\n event => {\n setNewItemText(event.currentTarget.value);\n },\n [setNewItemText],\n );\n\n const removeItem = useCallback(\n itemToRemove => setItems(items.filter(item => item !== itemToRemove)),\n [items],\n );\n\n const toggleItem = useCallback(\n itemToToggle => {\n // Dont use indexOf()\n // because editing props in DevTools creates a new Object.\n const index = items.findIndex(item => item.id === itemToToggle.id);\n\n setItems(\n items\n .slice(0, index)\n .concat({\n ...itemToToggle,\n isComplete: !itemToToggle.isComplete,\n })\n .concat(items.slice(index + 1)),\n );\n },\n [items],\n );\n\n return (\n <Fragment>\n <h1>List</h1>\n <input\n type=\"text\"\n placeholder=\"New list item...\"\n value={newItemText}\n onChange={handleChange}\n onKeyPress={handleKeyPress}\n />\n <button disabled={newItemText === ''} onClick={handleClick}>\n <span role=\"img\" aria-label=\"Add item\">\n Add\n </span>\n </button>\n <ul>\n {items.map(item => (\n <ListItem\n key={item.id}\n item={item}\n removeItem={removeItem}\n toggleItem={toggleItem}\n />\n ))}\n </ul>\n </Fragment>\n );\n}\n"],"names":["Component","count","setCount","useState","isDarkMode","useIsDarkMode","useEffect","handleClick","React","useEffectCreate","ThemeContext","createContext","useTheme","theme","useContext","useDebugValue","require","ListItem","item","removeItem","toggleItem","handleDelete","useCallback","handleToggle","React.createElement","isComplete","text","List","props","newItemText","setNewItemText","items","setItems","id","uid","setUID","handleKeyPress","event","key","handleChange","currentTarget","value","itemToRemove","filter","itemToToggle","index","findIndex","slice","concat","Fragment","map"],"mappings":"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"}
\ No newline at end of file
1
+{"version":3,"file":"index.js","sources":["../../ComponentWithCustomHook.js","../../useTheme.js","../../ComponentWithExternalCustomHooks.js","../../ComponentWithMultipleHooksPerLine.js","../../Example.js","../../InlineRequire.js","../../ToDoList.js"],"sourcesContent":["/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport React, {useEffect, useState} from 'react';\n\nexport function Component() {\n const [count, setCount] = useState(0);\n const isDarkMode = useIsDarkMode();\n\n useEffect(() => {\n // ...\n }, []);\n\n const handleClick = () => setCount(count + 1);\n\n return (\n <>\n <div>Dark mode? {isDarkMode}</div>\n <div>Count: {count}</div>\n <button onClick={handleClick}>Update count</button>\n </>\n );\n}\n\nfunction useIsDarkMode() {\n const [isDarkMode] = useState(false);\n\n useEffect(function useEffectCreate() {\n // Here is where we may listen to a \"theme\" event...\n }, []);\n\n return isDarkMode;\n}\n","/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {createContext, useContext, useDebugValue} from 'react';\n\nexport const ThemeContext = createContext('bright');\n\nexport default function useTheme() {\n const theme = useContext(ThemeContext);\n useDebugValue(theme);\n return theme;\n}\n","/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport React from 'react';\nimport useTheme from './useTheme';\n\nexport function Component() {\n const theme = useTheme();\n\n return <div>theme: {theme}</div>;\n}\n","/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {createContext, useContext} from 'react';\n\nconst A = createContext(1);\nconst B = createContext(2);\n\nexport function Component() {\n const a = useContext(A);\n const b = useContext(B);\n\n // prettier-ignore\n const c = useContext(A), d = useContext(B); // eslint-disable-line one-var\n\n return a + b + c + d;\n}\n","/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport React, {useState} from 'react';\n\nexport function Component() {\n const [count, setCount] = useState(0);\n\n return (\n <div>\n <p>You clicked {count} times</p>\n <button onClick={() => setCount(count + 1)}>Click me</button>\n </div>\n );\n}\n","/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport function Component() {\n const [count] = require('react').useState(0);\n\n return count;\n}\n","/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport * as React from 'react';\nimport {Fragment, useCallback, useState} from 'react';\n\nexport function ListItem({item, removeItem, toggleItem}) {\n const handleDelete = useCallback(() => {\n removeItem(item);\n }, [item, removeItem]);\n\n const handleToggle = useCallback(() => {\n toggleItem(item);\n }, [item, toggleItem]);\n\n return (\n <li>\n <button onClick={handleDelete}>Delete</button>\n <label>\n <input\n checked={item.isComplete}\n onChange={handleToggle}\n type=\"checkbox\"\n />{' '}\n {item.text}\n </label>\n </li>\n );\n}\n\nexport function List(props) {\n const [newItemText, setNewItemText] = useState('');\n const [items, setItems] = useState([\n {id: 1, isComplete: true, text: 'First'},\n {id: 2, isComplete: true, text: 'Second'},\n {id: 3, isComplete: false, text: 'Third'},\n ]);\n const [uid, setUID] = useState(4);\n\n const handleClick = useCallback(() => {\n if (newItemText !== '') {\n setItems([\n ...items,\n {\n id: uid,\n isComplete: false,\n text: newItemText,\n },\n ]);\n setUID(uid + 1);\n setNewItemText('');\n }\n }, [newItemText, items, uid]);\n\n const handleKeyPress = useCallback(\n event => {\n if (event.key === 'Enter') {\n handleClick();\n }\n },\n [handleClick],\n );\n\n const handleChange = useCallback(\n event => {\n setNewItemText(event.currentTarget.value);\n },\n [setNewItemText],\n );\n\n const removeItem = useCallback(\n itemToRemove => setItems(items.filter(item => item !== itemToRemove)),\n [items],\n );\n\n const toggleItem = useCallback(\n itemToToggle => {\n // Dont use indexOf()\n // because editing props in DevTools creates a new Object.\n const index = items.findIndex(item => item.id === itemToToggle.id);\n\n setItems(\n items\n .slice(0, index)\n .concat({\n ...itemToToggle,\n isComplete: !itemToToggle.isComplete,\n })\n .concat(items.slice(index + 1)),\n );\n },\n [items],\n );\n\n return (\n <Fragment>\n <h1>List</h1>\n <input\n type=\"text\"\n placeholder=\"New list item...\"\n value={newItemText}\n onChange={handleChange}\n onKeyPress={handleKeyPress}\n />\n <button disabled={newItemText === ''} onClick={handleClick}>\n <span role=\"img\" aria-label=\"Add item\">\n Add\n </span>\n </button>\n <ul>\n {items.map(item => (\n <ListItem\n key={item.id}\n item={item}\n removeItem={removeItem}\n toggleItem={toggleItem}\n />\n ))}\n </ul>\n </Fragment>\n );\n}\n"],"names":["Component","count","setCount","useState","isDarkMode","useIsDarkMode","useEffect","handleClick","React","useEffectCreate","ThemeContext","createContext","useTheme","theme","useContext","useDebugValue","A","B","a","b","c","d","require","ListItem","item","removeItem","toggleItem","handleDelete","useCallback","handleToggle","React.createElement","isComplete","text","List","props","newItemText","setNewItemText","items","setItems","id","uid","setUID","handleKeyPress","event","key","handleChange","currentTarget","value","itemToRemove","filter","itemToToggle","index","findIndex","slice","concat","Fragment","map"],"mappings":"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"}
\ No newline at end of file
packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/ComponentWithMultipleHooksPerLine.js
new
+30
@@ -0,0 +1,30 @@
1
+"use strict";
2
+
3
+Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+});
6
+exports.Component = Component;
7
+
8
+var _react = require("react");
9
+
10
+/**
11
+ * Copyright (c) Facebook, Inc. and its affiliates.
12
+ *
13
+ * This source code is licensed under the MIT license found in the
14
+ * LICENSE file in the root directory of this source tree.
15
+ *
16
+ * @flow
17
+ */
18
+const A = /*#__PURE__*/(0, _react.createContext)(1);
19
+const B = /*#__PURE__*/(0, _react.createContext)(2);
20
+
21
+function Component() {
22
+ const a = (0, _react.useContext)(A);
23
+ const b = (0, _react.useContext)(B); // prettier-ignore
24
+
25
+ const c = (0, _react.useContext)(A),
26
+ d = (0, _react.useContext)(B); // eslint-disable-line one-var
27
+
28
+ return a + b + c + d;
29
+}
30
+//# sourceMappingURL=ComponentWithMultipleHooksPerLine.js.map
\ No newline at end of file
packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/ComponentWithMultipleHooksPerLine.js.map
new
+1
@@ -0,0 +1 @@
1
+{"version":3,"sources":["ComponentWithMultipleHooksPerLine.js"],"names":["A","B","Component","a","b","c","d"],"mappings":";;;;;;;AASA;;AATA;;;;;;;;AAWA,MAAMA,CAAC,gBAAG,0BAAc,CAAd,CAAV;AACA,MAAMC,CAAC,gBAAG,0BAAc,CAAd,CAAV;;AAEO,SAASC,SAAT,GAAqB;AAC1B,QAAMC,CAAC,GAAG,uBAAWH,CAAX,CAAV;AACA,QAAMI,CAAC,GAAG,uBAAWH,CAAX,CAAV,CAF0B,CAI1B;;AACA,QAAMI,CAAC,GAAG,uBAAWL,CAAX,CAAV;AAAA,QAAyBM,CAAC,GAAG,uBAAWL,CAAX,CAA7B,CAL0B,CAKkB;;AAE5C,SAAOE,CAAC,GAAGC,CAAJ,GAAQC,CAAR,GAAYC,CAAnB;AACD","sourcesContent":["/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nimport {createContext, useContext} from 'react';\n\nconst A = createContext(1);\nconst B = createContext(2);\n\nexport function Component() {\n const a = useContext(A);\n const b = useContext(B);\n\n // prettier-ignore\n const c = useContext(A), d = useContext(B); // eslint-disable-line one-var\n\n return a + b + c + d;\n}\n"]}
\ No newline at end of file
packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/index.js
+8
@@ -15,6 +15,12 @@ Object.defineProperty(exports, "ComponentWithExternalCustomHooks", {
15
return _ComponentWithExternalCustomHooks.Component;
16
}
17
});
18
+Object.defineProperty(exports, "ComponentWithMultipleHooksPerLine", {
19
+ enumerable: true,
20
+ get: function () {
21
+ return _ComponentWithMultipleHooksPerLine.Component;
22
+ }
23
+});
24
Object.defineProperty(exports, "Example", {
25
enumerable: true,
26
get: function () {
@@ -39,6 +45,8 @@ var _ComponentWithCustomHook = require("./ComponentWithCustomHook");
45
46
var _ComponentWithExternalCustomHooks = require("./ComponentWithExternalCustomHooks");
47
48
+var _ComponentWithMultipleHooksPerLine = require("./ComponentWithMultipleHooksPerLine");
49
+
50
var _Example = require("./Example");
51
52
var _InlineRequire = require("./InlineRequire");
packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/index.js.map
+1
-1
@@ -1 +1 @@
1
-{"version":3,"sources":["index.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AASA;;AACA;;AACA;;AACA;;AACA;;;;AAEA","sourcesContent":["/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {Component as ComponentWithCustomHook} from './ComponentWithCustomHook';\nexport {Component as ComponentWithExternalCustomHooks} from './ComponentWithExternalCustomHooks';\nexport {Component as Example} from './Example';\nexport {Component as InlineRequire} from './InlineRequire';\nimport * as ToDoList from './ToDoList';\nexport {ToDoList};\nexport {default as useTheme} from './useTheme';\n"]}
\ No newline at end of file
1
+{"version":3,"sources":["index.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AASA;;AACA;;AACA;;AACA;;AACA;;AACA;;;;AAEA","sourcesContent":["/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @flow\n */\n\nexport {Component as ComponentWithCustomHook} from './ComponentWithCustomHook';\nexport {Component as ComponentWithExternalCustomHooks} from './ComponentWithExternalCustomHooks';\nexport {Component as ComponentWithMultipleHooksPerLine} from './ComponentWithMultipleHooksPerLine';\nexport {Component as Example} from './Example';\nexport {Component as InlineRequire} from './InlineRequire';\nimport * as ToDoList from './ToDoList';\nexport {ToDoList};\nexport {default as useTheme} from './useTheme';\n"]}
\ No newline at end of file
packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/inline/ComponentWithMultipleHooksPerLine.js
new
+30
@@ -0,0 +1,30 @@
1
+"use strict";
2
+
3
+Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+});
6
+exports.Component = Component;
7
+
8
+var _react = require("react");
9
+
10
+/**
11
+ * Copyright (c) Facebook, Inc. and its affiliates.
12
+ *
13
+ * This source code is licensed under the MIT license found in the
14
+ * LICENSE file in the root directory of this source tree.
15
+ *
16
+ * @flow
17
+ */
18
+const A = /*#__PURE__*/(0, _react.createContext)(1);
19
+const B = /*#__PURE__*/(0, _react.createContext)(2);
20
+
21
+function Component() {
22
+ const a = (0, _react.useContext)(A);
23
+ const b = (0, _react.useContext)(B); // prettier-ignore
24
+
25
+ const c = (0, _react.useContext)(A),
26
+ d = (0, _react.useContext)(B); // eslint-disable-line one-var
27
+
28
+ return a + b + c + d;
29
+}
30
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhNdWx0aXBsZUhvb2tzUGVyTGluZS5qcyJdLCJuYW1lcyI6WyJBIiwiQiIsIkNvbXBvbmVudCIsImEiLCJiIiwiYyIsImQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFTQTs7QUFUQTs7Ozs7Ozs7QUFXQSxNQUFNQSxDQUFDLGdCQUFHLDBCQUFjLENBQWQsQ0FBVjtBQUNBLE1BQU1DLENBQUMsZ0JBQUcsMEJBQWMsQ0FBZCxDQUFWOztBQUVPLFNBQVNDLFNBQVQsR0FBcUI7QUFDMUIsUUFBTUMsQ0FBQyxHQUFHLHVCQUFXSCxDQUFYLENBQVY7QUFDQSxRQUFNSSxDQUFDLEdBQUcsdUJBQVdILENBQVgsQ0FBVixDQUYwQixDQUkxQjs7QUFDQSxRQUFNSSxDQUFDLEdBQUcsdUJBQVdMLENBQVgsQ0FBVjtBQUFBLFFBQXlCTSxDQUFDLEdBQUcsdUJBQVdMLENBQVgsQ0FBN0IsQ0FMMEIsQ0FLa0I7O0FBRTVDLFNBQU9FLENBQUMsR0FBR0MsQ0FBSixHQUFRQyxDQUFSLEdBQVlDLENBQW5CO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IHtjcmVhdGVDb250ZXh0LCB1c2VDb250ZXh0fSBmcm9tICdyZWFjdCc7XG5cbmNvbnN0IEEgPSBjcmVhdGVDb250ZXh0KDEpO1xuY29uc3QgQiA9IGNyZWF0ZUNvbnRleHQoMik7XG5cbmV4cG9ydCBmdW5jdGlvbiBDb21wb25lbnQoKSB7XG4gIGNvbnN0IGEgPSB1c2VDb250ZXh0KEEpO1xuICBjb25zdCBiID0gdXNlQ29udGV4dChCKTtcblxuICAvLyBwcmV0dGllci1pZ25vcmVcbiAgY29uc3QgYyA9IHVzZUNvbnRleHQoQSksIGQgPSB1c2VDb250ZXh0KEIpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG9uZS12YXJcblxuICByZXR1cm4gYSArIGIgKyBjICsgZDtcbn1cbiJdfQ==
\ No newline at end of file
packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/inline/index.js
+9
-1
@@ -15,6 +15,12 @@ Object.defineProperty(exports, "ComponentWithExternalCustomHooks", {
15
return _ComponentWithExternalCustomHooks.Component;
16
}
17
});
18
+Object.defineProperty(exports, "ComponentWithMultipleHooksPerLine", {
19
+ enumerable: true,
20
+ get: function () {
21
+ return _ComponentWithMultipleHooksPerLine.Component;
22
+ }
23
+});
24
Object.defineProperty(exports, "Example", {
25
enumerable: true,
26
get: function () {
@@ -39,6 +45,8 @@ var _ComponentWithCustomHook = require("./ComponentWithCustomHook");
45
46
var _ComponentWithExternalCustomHooks = require("./ComponentWithExternalCustomHooks");
47
48
+var _ComponentWithMultipleHooksPerLine = require("./ComponentWithMultipleHooksPerLine");
49
+
50
var _Example = require("./Example");
51
52
var _InlineRequire = require("./InlineRequire");
@@ -54,4 +62,4 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
62
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
63
64
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
57
-//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImluZGV4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFTQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7OztBQUVBIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5cbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFdpdGhDdXN0b21Ib29rfSBmcm9tICcuL0NvbXBvbmVudFdpdGhDdXN0b21Ib29rJztcbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFdpdGhFeHRlcm5hbEN1c3RvbUhvb2tzfSBmcm9tICcuL0NvbXBvbmVudFdpdGhFeHRlcm5hbEN1c3RvbUhvb2tzJztcbmV4cG9ydCB7Q29tcG9uZW50IGFzIEV4YW1wbGV9IGZyb20gJy4vRXhhbXBsZSc7XG5leHBvcnQge0NvbXBvbmVudCBhcyBJbmxpbmVSZXF1aXJlfSBmcm9tICcuL0lubGluZVJlcXVpcmUnO1xuaW1wb3J0ICogYXMgVG9Eb0xpc3QgZnJvbSAnLi9Ub0RvTGlzdCc7XG5leHBvcnQge1RvRG9MaXN0fTtcbmV4cG9ydCB7ZGVmYXVsdCBhcyB1c2VUaGVtZX0gZnJvbSAnLi91c2VUaGVtZSc7XG4iXX0=
\ No newline at end of file
65
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImluZGV4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFTQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7OztBQUVBIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5cbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFdpdGhDdXN0b21Ib29rfSBmcm9tICcuL0NvbXBvbmVudFdpdGhDdXN0b21Ib29rJztcbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFdpdGhFeHRlcm5hbEN1c3RvbUhvb2tzfSBmcm9tICcuL0NvbXBvbmVudFdpdGhFeHRlcm5hbEN1c3RvbUhvb2tzJztcbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFdpdGhNdWx0aXBsZUhvb2tzUGVyTGluZX0gZnJvbSAnLi9Db21wb25lbnRXaXRoTXVsdGlwbGVIb29rc1BlckxpbmUnO1xuZXhwb3J0IHtDb21wb25lbnQgYXMgRXhhbXBsZX0gZnJvbSAnLi9FeGFtcGxlJztcbmV4cG9ydCB7Q29tcG9uZW50IGFzIElubGluZVJlcXVpcmV9IGZyb20gJy4vSW5saW5lUmVxdWlyZSc7XG5pbXBvcnQgKiBhcyBUb0RvTGlzdCBmcm9tICcuL1RvRG9MaXN0JztcbmV4cG9ydCB7VG9Eb0xpc3R9O1xuZXhwb3J0IHtkZWZhdWx0IGFzIHVzZVRoZW1lfSBmcm9tICcuL3VzZVRoZW1lJztcbiJdfQ==
\ No newline at end of file
packages/react-devtools-extensions/src/__tests__/__source__/__untransformed__/ComponentWithNamedCustomHooks.js
new
+31
@@ -0,0 +1,31 @@
1
+/**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow
8
+ */
9
+
10
+const {useDebugValue, useState} = require('react');
11
+
12
+function Component(props) {
13
+ const foo = useCustomHookOne();
14
+ // This cae is ignored;
15
+ // the meaning of a tuple assignment for a custom hook is unclear.
16
+ const [bar] = useCustomHookTwo();
17
+ return `${foo}-${bar}`;
18
+}
19
+
20
+function useCustomHookOne() {
21
+ // DebugValue hook should not appear in log.
22
+ useDebugValue('example');
23
+ return true;
24
+}
25
+
26
+function useCustomHookTwo() {
27
+ const [baz, setBaz] = useState(true);
28
+ return [baz, setBaz];
29
+}
30
+
31
+module.exports = {Component};
\ No newline at end of file
packages/react-devtools-extensions/src/__tests__/__source__/__untransformed__/ComponentWithUnnamedCustomHooks.js
new
+29
@@ -0,0 +1,29 @@
1
+/**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow
8
+ */
9
+
10
+const {useDebugValue} = require('react');
11
+
12
+function Component(props) {
13
+ useCustomHookOne();
14
+ const [bar] = useCustomHookTwo();
15
+ return bar;
16
+}
17
+
18
+function useCustomHookOne() {
19
+ // DebugValue hook should not appear in log.
20
+ useDebugValue('example');
21
+}
22
+
23
+function useCustomHookTwo() {
24
+ // DebugValue hook should not appear in log.
25
+ useDebugValue('example');
26
+ return [true];
27
+}
28
+
29
+module.exports = {Component};
\ No newline at end of file
packages/react-devtools-extensions/src/__tests__/__source__/__untransformed__/ComponentWithUseEffect.js
new
+19
@@ -0,0 +1,19 @@
1
+/**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow
8
+ */
9
+
10
+const React = require('react');
11
+const {useEffect} = React;
12
+
13
+function Component(props) {
14
+ useEffect(() => {});
15
+ React.useLayoutEffect(() => () => {});
16
+ return null;
17
+}
18
+
19
+module.exports = {Component};
\ No newline at end of file
packages/react-devtools-extensions/src/__tests__/__source__/__untransformed__/ComponentWithUseReducer.js
new
+20
@@ -0,0 +1,20 @@
1
+/**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow
8
+ */
9
+
10
+const React = require('react');
11
+const {useReducer} = React;
12
+
13
+function Component(props) {
14
+ const [foo] = useReducer(true);
15
+ const [bar] = useReducer(true);
16
+ const [baz] = React.useReducer(true);
17
+ return `${foo}-${bar}-${baz}`;
18
+}
19
+
20
+module.exports = {Component};
\ No newline at end of file
packages/react-devtools-extensions/src/__tests__/__source__/__untransformed__/ComponentWithUseState.js
new
+20
@@ -0,0 +1,20 @@
1
+/**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow
8
+ */
9
+
10
+const React = require('react');
11
+const {useState} = React;
12
+
13
+function Component(props) {
14
+ const [foo] = useState(true);
15
+ const bar = useState(true);
16
+ const [baz] = React.useState(true);
17
+ return `${foo}-${bar}-${baz}`;
18
+}
19
+
20
+module.exports = {Component};
\ No newline at end of file
packages/react-devtools-extensions/src/__tests__/__source__/__untransformed__/README.md
new
+1
@@ -0,0 +1 @@
1
+The JavaScript source files in this directory are not linted or pre-processed in any way. This is intentional, since they are used by the `parseHookNames-test` to test the behavior of "uncompiled" JavaScript (without source maps).
\ No newline at end of file
packages/react-devtools-extensions/src/__tests__/__source__/index.js
+1
@@ -9,6 +9,7 @@
9
10
export {Component as ComponentWithCustomHook} from './ComponentWithCustomHook';
11
export {Component as ComponentWithExternalCustomHooks} from './ComponentWithExternalCustomHooks';
12
+export {Component as ComponentWithMultipleHooksPerLine} from './ComponentWithMultipleHooksPerLine';
13
export {Component as Example} from './Example';
14
export {Component as InlineRequire} from './InlineRequire';
15
import * as ToDoList from './ToDoList';
packages/react-devtools-extensions/src/__tests__/parseHookNames-test.js
+38
-60
@@ -7,6 +7,10 @@
7
* @flow
8
*/
9
10
+// Note that this test uses React components declared in the "__source__" directory.
11
+// This is done to control if and how the code is transformed at runtime.
12
+// Do not declare test components within this test file as it is very fragile.
13
+
14
describe('parseHookNames', () => {
15
let fetchMock;
16
let inspectHooks;
@@ -87,65 +91,29 @@ describe('parseHookNames', () => {
91
}
92
93
it('should parse names for useState()', async () => {
90
- const React = require('react');
91
- const {useState} = React;
92
- function Component(props) {
93
- const [foo] = useState(true);
94
- const bar = useState(true);
95
- const [baz] = React.useState(true);
96
- return `${foo}-${bar}-${baz}`;
97
- }
98
-
94
+ const Component = require('./__source__/__untransformed__/ComponentWithUseState')
95
+ .Component;
96
const hookNames = await getHookNamesForComponent(Component);
97
expectHookNamesToEqual(hookNames, ['foo', 'bar', 'baz']);
98
});
99
100
it('should parse names for useReducer()', async () => {
104
- const React = require('react');
105
- const {useReducer} = React;
106
- function Component(props) {
107
- const [foo] = useReducer(true);
108
- const [bar] = useReducer(true);
109
- const [baz] = React.useReducer(true);
110
- return `${foo}-${bar}-${baz}`;
111
- }
112
-
101
+ const Component = require('./__source__/__untransformed__/ComponentWithUseReducer')
102
+ .Component;
103
const hookNames = await getHookNamesForComponent(Component);
104
expectHookNamesToEqual(hookNames, ['foo', 'bar', 'baz']);
105
});
106
107
it('should return null for hooks without names like useEffect', async () => {
118
- const React = require('react');
119
- const {useEffect} = React;
120
- function Component(props) {
121
- useEffect(() => {});
122
- React.useLayoutEffect(() => () => {});
123
- return null;
124
- }
125
-
108
+ const Component = require('./__source__/__untransformed__/ComponentWithUseEffect')
109
+ .Component;
110
const hookNames = await getHookNamesForComponent(Component);
111
expectHookNamesToEqual(hookNames, []); // No hooks with names
112
});
113
114
it('should parse names for custom hooks', async () => {
131
- const {useDebugValue, useState} = require('react');
132
- function useCustomHookOne() {
133
- // DebugValue hook should not appear in log.
134
- useDebugValue('example');
135
- return true;
136
- }
137
- function useCustomHookTwo() {
138
- const [baz, setBaz] = useState(true);
139
- return [baz, setBaz];
140
- }
141
- function Component(props) {
142
- const foo = useCustomHookOne();
143
- // This cae is ignored;
144
- // the meaning of a tuple assignment for a custom hook is unclear.
145
- const [bar] = useCustomHookTwo();
146
- return `${foo}-${bar}`;
147
- }
148
-
115
+ const Component = require('./__source__/__untransformed__/ComponentWithNamedCustomHooks')
116
+ .Component;
117
const hookNames = await getHookNamesForComponent(Component);
118
expectHookNamesToEqual(hookNames, [
119
'foo',
@@ -155,22 +123,8 @@ describe('parseHookNames', () => {
123
});
124
125
it('should return null for custom hooks without explicit names', async () => {
158
- const {useDebugValue} = require('react');
159
- function useCustomHookOne() {
160
- // DebugValue hook should not appear in log.
161
- useDebugValue('example');
162
- }
163
- function useCustomHookTwo() {
164
- // DebugValue hook should not appear in log.
165
- useDebugValue('example');
166
- return [true];
167
- }
168
- function Component(props) {
169
- useCustomHookOne();
170
- const [bar] = useCustomHookTwo();
171
- return bar;
172
- }
173
-
126
+ const Component = require('./__source__/__untransformed__/ComponentWithUnnamedCustomHooks')
127
+ .Component;
128
const hookNames = await getHookNamesForComponent(Component);
129
expectHookNamesToEqual(hookNames, [
130
null, // Custom hooks can have names, but this one does not even return a value.
@@ -267,6 +221,30 @@ describe('parseHookNames', () => {
221
); // bundle source map
222
});
223
224
+ it('should work when multiple hooks are on a line', async () => {
225
+ async function test(path, name = 'Component') {
226
+ const Component = require(path)[name];
227
+ const hookNames = await getHookNamesForComponent(Component);
228
+ expectHookNamesToEqual(hookNames, [
229
+ 'a', // useContext()
230
+ 'b', // useContext()
231
+ 'c', // useContext()
232
+ 'd', // useContext()
233
+ ]);
234
+ }
235
+
236
+ await test(
237
+ './__source__/__compiled__/inline/ComponentWithMultipleHooksPerLine',
238
+ ); // inline source map
239
+ await test(
240
+ './__source__/__compiled__/external/ComponentWithMultipleHooksPerLine',
241
+ ); // external source map
242
+ await test(
243
+ './__source__/__compiled__/bundle',
244
+ 'ComponentWithMultipleHooksPerLine',
245
+ ); // bundle source map
246
+ });
247
+
248
// TODO Inline require (e.g. require("react").useState()) isn't supported yet.
249
// Maybe this isn't an important use case to support,
250
// since inline requires are most likely to exist in compiled source (if at all).
packages/react-devtools-extensions/src/astUtils.js
+21
-3
@@ -29,9 +29,25 @@ const AST_NODE_TYPES = Object.freeze({
29
});
30
31
// Check if line number obtained from source map and the line number in hook node match
32
-function checkNodeLocation(path: NodePath, line: number): boolean {
32
+function checkNodeLocation(
33
+ path: NodePath,
34
+ line: number,
35
+ column: number,
36
+): boolean {
37
const {start, end} = path.node.loc;
34
- return line >= start.line && line <= end.line;
38
+
39
+ if (line < start.line || line > end.line) {
40
+ return false;
41
+ }
42
+
43
+ if (
44
+ (line === start.line && column < start.column) ||
45
+ (line === end.line && column > end.column)
46
+ ) {
47
+ return false;
48
+ }
49
+
50
+ return true;
51
}
52
53
// Checks whether hookNode is a member of targetHookNode
@@ -91,13 +107,15 @@ export function getHookName(
107
originalSourceAST: mixed,
108
originalSourceCode: string,
109
originalSourceLineNumber: number,
110
+ originalSourceColumnNumber: number,
111
): string | null {
112
const hooksFromAST = getPotentialHookDeclarationsFromAST(originalSourceAST);
113
114
const potentialReactHookASTNode = hooksFromAST.find(node => {
115
const nodeLocationCheck = checkNodeLocation(
116
node,
100
- ((originalSourceLineNumber: any): number),
117
+ originalSourceLineNumber,
118
+ originalSourceColumnNumber,
119
);
120
const hookDeclaractionCheck = isConfirmedHookDeclaration(node);
121
return nodeLocationCheck && hookDeclaractionCheck;
packages/react-devtools-extensions/src/parseHookNames.js
+13
-7
@@ -376,32 +376,37 @@ function findHookNames(
376
377
const sourceConsumer = hookSourceData.sourceConsumer;
378
379
+ let originalSourceColumnNumber;
380
let originalSourceLineNumber;
381
if (areSourceMapsAppliedToErrors() || !sourceConsumer) {
382
// Either the current environment automatically applies source maps to errors,
383
// or the current code had no source map to begin with.
384
// Either way, we don't need to convert the Error stack frame locations.
385
+ originalSourceColumnNumber = columnNumber;
386
originalSourceLineNumber = lineNumber;
387
} else {
386
- originalSourceLineNumber = sourceConsumer.originalPositionFor({
388
+ const position = sourceConsumer.originalPositionFor({
389
line: lineNumber,
390
391
// Column numbers are representated differently between tools/engines.
392
// For more info see https://github.com/facebook/react/issues/21792#issuecomment-873171991
393
column: columnNumber - 1,
392
- }).line;
394
+ });
395
+
396
+ originalSourceColumnNumber = position.column;
397
+ originalSourceLineNumber = position.line;
398
}
399
400
if (__DEBUG__) {
401
console.log(
397
- 'findHookNames() mapped line number',
398
- lineNumber,
399
- 'to',
400
- originalSourceLineNumber,
402
+ `findHookNames() mapped line ${lineNumber}->${originalSourceLineNumber} and column ${columnNumber}->${originalSourceColumnNumber}`,
403
);
404
}
405
404
- if (originalSourceLineNumber === null) {
406
+ if (
407
+ originalSourceLineNumber === null ||
408
+ originalSourceColumnNumber === null
409
+ ) {
410
return null;
411
}
412
@@ -410,6 +415,7 @@ function findHookNames(
415
hookSourceData.originalSourceAST,
416
((hookSourceData.originalSourceCode: any): string),
417
((originalSourceLineNumber: any): number),
418
+ originalSourceColumnNumber,
419
);
420
421
if (__DEBUG__) {
scripts/jest/config.build-devtools.js
+1
@@ -59,6 +59,7 @@ module.exports = Object.assign({}, baseConfig, {
59
'/node_modules/',
60
'<rootDir>/build2/',
61
'/__compiled__/',
62
+ '/__untransformed__/',
63
],
64
testRegex:
65
'packages/react-devtools-(extensions|shared)/src/__tests__/[^]+.test.js$',
scripts/prettier/index.js
+1
@@ -30,6 +30,7 @@ const files = glob
30
'**/node_modules/**',
31
'**/cjs/**',
32
'**/__compiled__/**',
33
+ '**/__untransformed__/**',
34
'packages/react-devtools-extensions/src/ErrorTesterCompiled.js',
35
],
36
})