@samitouri / QOS-React-2 / commits / f52b73f9d0

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 })