diff --git a/packages/react-devtools-extensions/package.json b/packages/react-devtools-extensions/package.json index 1949edbd023..40954c44251 100644 --- a/packages/react-devtools-extensions/package.json +++ b/packages/react-devtools-extensions/package.json @@ -19,6 +19,7 @@ "update-mock-source-maps": "node ./src/__tests__/updateMockSourceMaps.js" }, "devDependencies": { + "acorn-jsx": "^5.2.0", "@babel/core": "^7.11.1", "@babel/plugin-proposal-class-properties": "^7.10.4", "@babel/plugin-transform-flow-strip-types": "^7.10.4", @@ -44,6 +45,10 @@ "open": "^7.0.2", "os-name": "^3.1.0", "raw-loader": "^3.1.0", + "rollup": "^1.19.4", + "rollup-plugin-babel": "^4.0.1", + "rollup-plugin-commonjs": "^9.3.4", + "rollup-plugin-node-resolve": "^2.1.1", "source-map": "^0.8.0-beta.0", "style-loader": "^0.23.1", "web-ext": "^3.0.0", diff --git a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/bundle/index.js b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/bundle/index.js new file mode 100644 index 00000000000..6bb59864766 --- /dev/null +++ b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/bundle/index.js @@ -0,0 +1,198 @@ +'use strict'; + +Object.defineProperty(exports, '__esModule', { value: true }); + +function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } + +var React = require('react'); +var React__default = _interopDefault(React); + +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ +function Component() { + const [count, setCount] = React.useState(0); + const isDarkMode = useIsDarkMode(); + React.useEffect(() => {// ... + }, []); + + const handleClick = () => setCount(count + 1); + + return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement("div", null, "Dark mode? ", isDarkMode), /*#__PURE__*/React__default.createElement("div", null, "Count: ", count), /*#__PURE__*/React__default.createElement("button", { + onClick: handleClick + }, "Update count")); +} + +function useIsDarkMode() { + const [isDarkMode] = React.useState(false); + React.useEffect(function useEffectCreate() {// Here is where we may listen to a "theme" event... + }, []); + return isDarkMode; +} + +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ +const ThemeContext = /*#__PURE__*/React.createContext('bright'); +function useTheme() { + const theme = React.useContext(ThemeContext); + React.useDebugValue(theme); + return theme; +} + +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ +function Component$1() { + const theme = useTheme(); + return /*#__PURE__*/React__default.createElement("div", null, "theme: ", theme); +} + +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ +function Component$2() { + const [count, setCount] = React.useState(0); + return /*#__PURE__*/React__default.createElement("div", null, /*#__PURE__*/React__default.createElement("p", null, "You clicked ", count, " times"), /*#__PURE__*/React__default.createElement("button", { + onClick: () => setCount(count + 1) + }, "Click me")); +} + +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ +function Component$3() { + const [count] = require('react').useState(0); + + return count; +} + +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ +function ListItem({ + item, + removeItem, + toggleItem +}) { + const handleDelete = React.useCallback(() => { + removeItem(item); + }, [item, removeItem]); + const handleToggle = React.useCallback(() => { + toggleItem(item); + }, [item, toggleItem]); + return /*#__PURE__*/React.createElement("li", null, /*#__PURE__*/React.createElement("button", { + onClick: handleDelete + }, "Delete"), /*#__PURE__*/React.createElement("label", null, /*#__PURE__*/React.createElement("input", { + checked: item.isComplete, + onChange: handleToggle, + type: "checkbox" + }), ' ', item.text)); +} +function List(props) { + const [newItemText, setNewItemText] = React.useState(''); + const [items, setItems] = React.useState([{ + id: 1, + isComplete: true, + text: 'First' + }, { + id: 2, + isComplete: true, + text: 'Second' + }, { + id: 3, + isComplete: false, + text: 'Third' + }]); + const [uid, setUID] = React.useState(4); + const handleClick = React.useCallback(() => { + if (newItemText !== '') { + setItems([...items, { + id: uid, + isComplete: false, + text: newItemText + }]); + setUID(uid + 1); + setNewItemText(''); + } + }, [newItemText, items, uid]); + const handleKeyPress = React.useCallback(event => { + if (event.key === 'Enter') { + handleClick(); + } + }, [handleClick]); + const handleChange = React.useCallback(event => { + setNewItemText(event.currentTarget.value); + }, [setNewItemText]); + const removeItem = React.useCallback(itemToRemove => setItems(items.filter(item => item !== itemToRemove)), [items]); + const toggleItem = React.useCallback(itemToToggle => { + // Dont use indexOf() + // because editing props in DevTools creates a new Object. + const index = items.findIndex(item => item.id === itemToToggle.id); + setItems(items.slice(0, index).concat({ ...itemToToggle, + isComplete: !itemToToggle.isComplete + }).concat(items.slice(index + 1))); + }, [items]); + return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("h1", null, "List"), /*#__PURE__*/React.createElement("input", { + type: "text", + placeholder: "New list item...", + value: newItemText, + onChange: handleChange, + onKeyPress: handleKeyPress + }), /*#__PURE__*/React.createElement("button", { + disabled: newItemText === '', + onClick: handleClick + }, /*#__PURE__*/React.createElement("span", { + role: "img", + "aria-label": "Add item" + }, "Add")), /*#__PURE__*/React.createElement("ul", null, items.map(item => /*#__PURE__*/React.createElement(ListItem, { + key: item.id, + item: item, + removeItem: removeItem, + toggleItem: toggleItem + })))); +} + +var ToDoList = /*#__PURE__*/Object.freeze({ + __proto__: null, + ListItem: ListItem, + List: List +}); + +exports.ComponentWithCustomHook = Component; +exports.ComponentWithExternalCustomHooks = Component$1; +exports.Example = Component$2; +exports.InlineRequire = Component$3; +exports.ToDoList = ToDoList; +exports.useTheme = useTheme; +//# sourceMappingURL=index.js.map diff --git a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/bundle/index.js.map b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/bundle/index.js.map new file mode 100644 index 00000000000..1a4fb620f92 --- /dev/null +++ b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/bundle/index.js.map @@ -0,0 +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
Dark mode? {isDarkMode}
\n
Count: {count}
\n \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
theme: {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, {useState} from 'react';\n\nexport function Component() {\n const [count, setCount] = useState(0);\n\n return (\n
\n

You clicked {count} times

\n \n
\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
  • \n \n \n
  • \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 \n

    List

    \n \n \n \n
    \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 diff --git a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/ComponentWithCustomHook.js b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/ComponentWithCustomHook.js index f76a1acedb8..e326d7a4962 100644 --- a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/ComponentWithCustomHook.js +++ b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/ComponentWithCustomHook.js @@ -33,10 +33,9 @@ function Component() { } function useIsDarkMode() { - const [isDarkMode, setIsDarkMode] = (0, _react.useState)(0); + const [isDarkMode] = (0, _react.useState)(false); (0, _react.useEffect)(function useEffectCreate() {// Here is where we may listen to a "theme" event... }, []); return isDarkMode; } -//# sourceMappingURL=ComponentWithCustomHook.js.map -//# sourceURL=ComponentWithCustomHook.js \ No newline at end of file +//# sourceMappingURL=ComponentWithCustomHook.js.map \ No newline at end of file diff --git a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/ComponentWithCustomHook.js.map b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/ComponentWithCustomHook.js.map index ac54e5738f9..3ebcb084abc 100644 --- a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/ComponentWithCustomHook.js.map +++ b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/ComponentWithCustomHook.js.map @@ -1 +1 @@ -{"version":3,"sources":["ComponentWithCustomHook.js"],"names":["Component","count","setCount","isDarkMode","useIsDarkMode","handleClick","setIsDarkMode","useEffectCreate"],"mappings":";;;;;;;AASA;;;;;;AATA;;;;;;;;AAWO,SAASA,SAAT,GAAqB;AAC1B,QAAM,CAACC,KAAD,EAAQC,QAAR,IAAoB,qBAAS,CAAT,CAA1B;AACA,QAAMC,UAAU,GAAGC,aAAa,EAAhC;AAEA,wBAAU,MAAM,CACd;AACD,GAFD,EAEG,EAFH;;AAIA,QAAMC,WAAW,GAAG,MAAMH,QAAQ,CAACD,KAAK,GAAG,CAAT,CAAlC;;AAEA,sBACE,yEACE,yDAAiBE,UAAjB,CADF,eAEE,qDAAaF,KAAb,CAFF,eAGE;AAAQ,IAAA,OAAO,EAAEI;AAAjB,oBAHF,CADF;AAOD;;AAED,SAASD,aAAT,GAAyB;AACvB,QAAM,CAACD,UAAD,EAAaG,aAAb,IAA8B,qBAAS,CAAT,CAApC;AAEA,wBAAU,SAASC,eAAT,GAA2B,CACnC;AACD,GAFD,EAEG,EAFH;AAIA,SAAOJ,UAAP;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 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
    Dark mode? {isDarkMode}
    \n
    Count: {count}
    \n \n \n );\n}\n\nfunction useIsDarkMode() {\n const [isDarkMode, setIsDarkMode] = useState(0);\n\n useEffect(function useEffectCreate() {\n // Here is where we may listen to a \"theme\" event...\n }, []);\n\n return isDarkMode;\n}"]} \ No newline at end of file +{"version":3,"sources":["ComponentWithCustomHook.js"],"names":["Component","count","setCount","isDarkMode","useIsDarkMode","handleClick","useEffectCreate"],"mappings":";;;;;;;AASA;;;;;;AATA;;;;;;;;AAWO,SAASA,SAAT,GAAqB;AAC1B,QAAM,CAACC,KAAD,EAAQC,QAAR,IAAoB,qBAAS,CAAT,CAA1B;AACA,QAAMC,UAAU,GAAGC,aAAa,EAAhC;AAEA,wBAAU,MAAM,CACd;AACD,GAFD,EAEG,EAFH;;AAIA,QAAMC,WAAW,GAAG,MAAMH,QAAQ,CAACD,KAAK,GAAG,CAAT,CAAlC;;AAEA,sBACE,yEACE,yDAAiBE,UAAjB,CADF,eAEE,qDAAaF,KAAb,CAFF,eAGE;AAAQ,IAAA,OAAO,EAAEI;AAAjB,oBAHF,CADF;AAOD;;AAED,SAASD,aAAT,GAAyB;AACvB,QAAM,CAACD,UAAD,IAAe,qBAAS,KAAT,CAArB;AAEA,wBAAU,SAASG,eAAT,GAA2B,CACnC;AACD,GAFD,EAEG,EAFH;AAIA,SAAOH,UAAP;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 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
    Dark mode? {isDarkMode}
    \n
    Count: {count}
    \n \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"]} \ No newline at end of file diff --git a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/ComponentWithExternalCustomHooks.js b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/ComponentWithExternalCustomHooks.js index dbdc0b3ade5..05aedb938b7 100644 --- a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/ComponentWithExternalCustomHooks.js +++ b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/ComponentWithExternalCustomHooks.js @@ -23,5 +23,4 @@ function Component() { const theme = (0, _useTheme.default)(); return /*#__PURE__*/_react.default.createElement("div", null, "theme: ", theme); } -//# sourceMappingURL=ComponentWithExternalCustomHooks.js.map -//# sourceURL=ComponentWithExternalCustomHooks.js \ No newline at end of file +//# sourceMappingURL=ComponentWithExternalCustomHooks.js.map \ No newline at end of file diff --git a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/Example.js b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/Example.js index b51d2b2c843..19134738824 100644 --- a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/Example.js +++ b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/Example.js @@ -25,5 +25,4 @@ function Component() { onClick: () => setCount(count + 1) }, "Click me")); } -//# sourceMappingURL=Example.js.map -//# sourceURL=Example.js \ No newline at end of file +//# sourceMappingURL=Example.js.map \ No newline at end of file diff --git a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/InlineRequire.js b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/InlineRequire.js index 4d025dab585..388aeda62b3 100644 --- a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/InlineRequire.js +++ b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/InlineRequire.js @@ -18,5 +18,4 @@ function Component() { return count; } -//# sourceMappingURL=InlineRequire.js.map -//# sourceURL=InlineRequire.js \ No newline at end of file +//# sourceMappingURL=InlineRequire.js.map \ No newline at end of file diff --git a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/ToDoList.js b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/ToDoList.js index d9cca2b089c..a6eb863b661 100644 --- a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/ToDoList.js +++ b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/ToDoList.js @@ -103,5 +103,4 @@ function List(props) { toggleItem: toggleItem })))); } -//# sourceMappingURL=ToDoList.js.map -//# sourceURL=ToDoList.js \ No newline at end of file +//# sourceMappingURL=ToDoList.js.map \ No newline at end of file diff --git a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/index.js b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/index.js new file mode 100644 index 00000000000..060a736cf1a --- /dev/null +++ b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/index.js @@ -0,0 +1,57 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "ComponentWithCustomHook", { + enumerable: true, + get: function () { + return _ComponentWithCustomHook.Component; + } +}); +Object.defineProperty(exports, "ComponentWithExternalCustomHooks", { + enumerable: true, + get: function () { + return _ComponentWithExternalCustomHooks.Component; + } +}); +Object.defineProperty(exports, "Example", { + enumerable: true, + get: function () { + return _Example.Component; + } +}); +Object.defineProperty(exports, "InlineRequire", { + enumerable: true, + get: function () { + return _InlineRequire.Component; + } +}); +Object.defineProperty(exports, "useTheme", { + enumerable: true, + get: function () { + return _useTheme.default; + } +}); +exports.ToDoList = void 0; + +var _ComponentWithCustomHook = require("./ComponentWithCustomHook"); + +var _ComponentWithExternalCustomHooks = require("./ComponentWithExternalCustomHooks"); + +var _Example = require("./Example"); + +var _InlineRequire = require("./InlineRequire"); + +var ToDoList = _interopRequireWildcard(require("./ToDoList")); + +exports.ToDoList = ToDoList; + +var _useTheme = _interopRequireDefault(require("./useTheme")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +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; } +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/index.js.map b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/index.js.map new file mode 100644 index 00000000000..0cd3aeaca07 --- /dev/null +++ b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/index.js.map @@ -0,0 +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 diff --git a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/useTheme.js b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/useTheme.js index b32aa123308..95bb454253e 100644 --- a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/useTheme.js +++ b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/external/useTheme.js @@ -24,5 +24,4 @@ function useTheme() { (0, _react.useDebugValue)(theme); return theme; } -//# sourceMappingURL=useTheme.js.map -//# sourceURL=useTheme.js \ No newline at end of file +//# sourceMappingURL=useTheme.js.map \ No newline at end of file diff --git a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/inline/ComponentWithCustomHook.js b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/inline/ComponentWithCustomHook.js index 85ac8a37c89..a382725a538 100644 --- a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/inline/ComponentWithCustomHook.js +++ b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/inline/ComponentWithCustomHook.js @@ -33,10 +33,9 @@ function Component() { } function useIsDarkMode() { - const [isDarkMode, setIsDarkMode] = (0, _react.useState)(0); + const [isDarkMode] = (0, _react.useState)(false); (0, _react.useEffect)(function useEffectCreate() {// Here is where we may listen to a "theme" event... }, []); return isDarkMode; } -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhDdXN0b21Ib29rLmpzIl0sIm5hbWVzIjpbIkNvbXBvbmVudCIsImNvdW50Iiwic2V0Q291bnQiLCJpc0RhcmtNb2RlIiwidXNlSXNEYXJrTW9kZSIsImhhbmRsZUNsaWNrIiwic2V0SXNEYXJrTW9kZSIsInVzZUVmZmVjdENyZWF0ZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQVNBOzs7Ozs7QUFUQTs7Ozs7Ozs7QUFXTyxTQUFTQSxTQUFULEdBQXFCO0FBQzFCLFFBQU0sQ0FBQ0MsS0FBRCxFQUFRQyxRQUFSLElBQW9CLHFCQUFTLENBQVQsQ0FBMUI7QUFDQSxRQUFNQyxVQUFVLEdBQUdDLGFBQWEsRUFBaEM7QUFFQSx3QkFBVSxNQUFNLENBQ2Q7QUFDRCxHQUZELEVBRUcsRUFGSDs7QUFJQSxRQUFNQyxXQUFXLEdBQUcsTUFBTUgsUUFBUSxDQUFDRCxLQUFLLEdBQUcsQ0FBVCxDQUFsQzs7QUFFQSxzQkFDRSx5RUFDRSx5REFBaUJFLFVBQWpCLENBREYsZUFFRSxxREFBYUYsS0FBYixDQUZGLGVBR0U7QUFBUSxJQUFBLE9BQU8sRUFBRUk7QUFBakIsb0JBSEYsQ0FERjtBQU9EOztBQUVELFNBQVNELGFBQVQsR0FBeUI7QUFDdkIsUUFBTSxDQUFDRCxVQUFELEVBQWFHLGFBQWIsSUFBOEIscUJBQVMsQ0FBVCxDQUFwQztBQUVBLHdCQUFVLFNBQVNDLGVBQVQsR0FBMkIsQ0FDbkM7QUFDRCxHQUZELEVBRUcsRUFGSDtBQUlBLFNBQU9KLFVBQVA7QUFDRCIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ29weXJpZ2h0IChjKSBGYWNlYm9vaywgSW5jLiBhbmQgaXRzIGFmZmlsaWF0ZXMuXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKlxuICogQGZsb3dcbiAqL1xuXG5pbXBvcnQgUmVhY3QsIHt1c2VFZmZlY3QsIHVzZVN0YXRlfSBmcm9tICdyZWFjdCc7XG5cbmV4cG9ydCBmdW5jdGlvbiBDb21wb25lbnQoKSB7XG4gIGNvbnN0IFtjb3VudCwgc2V0Q291bnRdID0gdXNlU3RhdGUoMCk7XG4gIGNvbnN0IGlzRGFya01vZGUgPSB1c2VJc0RhcmtNb2RlKCk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICAvLyAuLi5cbiAgfSwgW10pO1xuXG4gIGNvbnN0IGhhbmRsZUNsaWNrID0gKCkgPT4gc2V0Q291bnQoY291bnQgKyAxKTtcblxuICByZXR1cm4gKFxuICAgIDw+XG4gICAgICA8ZGl2PkRhcmsgbW9kZT8ge2lzRGFya01vZGV9PC9kaXY+XG4gICAgICA8ZGl2PkNvdW50OiB7Y291bnR9PC9kaXY+XG4gICAgICA8YnV0dG9uIG9uQ2xpY2s9e2hhbmRsZUNsaWNrfT5VcGRhdGUgY291bnQ8L2J1dHRvbj5cbiAgICA8Lz5cbiAgKTtcbn1cblxuZnVuY3Rpb24gdXNlSXNEYXJrTW9kZSgpIHtcbiAgY29uc3QgW2lzRGFya01vZGUsIHNldElzRGFya01vZGVdID0gdXNlU3RhdGUoMCk7XG5cbiAgdXNlRWZmZWN0KGZ1bmN0aW9uIHVzZUVmZmVjdENyZWF0ZSgpIHtcbiAgICAvLyBIZXJlIGlzIHdoZXJlIHdlIG1heSBsaXN0ZW4gdG8gYSBcInRoZW1lXCIgZXZlbnQuLi5cbiAgfSwgW10pO1xuXG4gIHJldHVybiBpc0RhcmtNb2RlO1xufSJdfQ== -//# sourceURL=ComponentWithCustomHook.js \ No newline at end of file +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhDdXN0b21Ib29rLmpzIl0sIm5hbWVzIjpbIkNvbXBvbmVudCIsImNvdW50Iiwic2V0Q291bnQiLCJpc0RhcmtNb2RlIiwidXNlSXNEYXJrTW9kZSIsImhhbmRsZUNsaWNrIiwidXNlRWZmZWN0Q3JlYXRlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBU0E7Ozs7OztBQVRBOzs7Ozs7OztBQVdPLFNBQVNBLFNBQVQsR0FBcUI7QUFDMUIsUUFBTSxDQUFDQyxLQUFELEVBQVFDLFFBQVIsSUFBb0IscUJBQVMsQ0FBVCxDQUExQjtBQUNBLFFBQU1DLFVBQVUsR0FBR0MsYUFBYSxFQUFoQztBQUVBLHdCQUFVLE1BQU0sQ0FDZDtBQUNELEdBRkQsRUFFRyxFQUZIOztBQUlBLFFBQU1DLFdBQVcsR0FBRyxNQUFNSCxRQUFRLENBQUNELEtBQUssR0FBRyxDQUFULENBQWxDOztBQUVBLHNCQUNFLHlFQUNFLHlEQUFpQkUsVUFBakIsQ0FERixlQUVFLHFEQUFhRixLQUFiLENBRkYsZUFHRTtBQUFRLElBQUEsT0FBTyxFQUFFSTtBQUFqQixvQkFIRixDQURGO0FBT0Q7O0FBRUQsU0FBU0QsYUFBVCxHQUF5QjtBQUN2QixRQUFNLENBQUNELFVBQUQsSUFBZSxxQkFBUyxLQUFULENBQXJCO0FBRUEsd0JBQVUsU0FBU0csZUFBVCxHQUEyQixDQUNuQztBQUNELEdBRkQsRUFFRyxFQUZIO0FBSUEsU0FBT0gsVUFBUDtBQUNEIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5cbmltcG9ydCBSZWFjdCwge3VzZUVmZmVjdCwgdXNlU3RhdGV9IGZyb20gJ3JlYWN0JztcblxuZXhwb3J0IGZ1bmN0aW9uIENvbXBvbmVudCgpIHtcbiAgY29uc3QgW2NvdW50LCBzZXRDb3VudF0gPSB1c2VTdGF0ZSgwKTtcbiAgY29uc3QgaXNEYXJrTW9kZSA9IHVzZUlzRGFya01vZGUoKTtcblxuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIC8vIC4uLlxuICB9LCBbXSk7XG5cbiAgY29uc3QgaGFuZGxlQ2xpY2sgPSAoKSA9PiBzZXRDb3VudChjb3VudCArIDEpO1xuXG4gIHJldHVybiAoXG4gICAgPD5cbiAgICAgIDxkaXY+RGFyayBtb2RlPyB7aXNEYXJrTW9kZX08L2Rpdj5cbiAgICAgIDxkaXY+Q291bnQ6IHtjb3VudH08L2Rpdj5cbiAgICAgIDxidXR0b24gb25DbGljaz17aGFuZGxlQ2xpY2t9PlVwZGF0ZSBjb3VudDwvYnV0dG9uPlxuICAgIDwvPlxuICApO1xufVxuXG5mdW5jdGlvbiB1c2VJc0RhcmtNb2RlKCkge1xuICBjb25zdCBbaXNEYXJrTW9kZV0gPSB1c2VTdGF0ZShmYWxzZSk7XG5cbiAgdXNlRWZmZWN0KGZ1bmN0aW9uIHVzZUVmZmVjdENyZWF0ZSgpIHtcbiAgICAvLyBIZXJlIGlzIHdoZXJlIHdlIG1heSBsaXN0ZW4gdG8gYSBcInRoZW1lXCIgZXZlbnQuLi5cbiAgfSwgW10pO1xuXG4gIHJldHVybiBpc0RhcmtNb2RlO1xufVxuIl19 \ No newline at end of file diff --git a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/inline/ComponentWithExternalCustomHooks.js b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/inline/ComponentWithExternalCustomHooks.js index b9812467b7f..fc925fdd5c2 100644 --- a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/inline/ComponentWithExternalCustomHooks.js +++ b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/inline/ComponentWithExternalCustomHooks.js @@ -23,5 +23,4 @@ function Component() { const theme = (0, _useTheme.default)(); return /*#__PURE__*/_react.default.createElement("div", null, "theme: ", theme); } -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhFeHRlcm5hbEN1c3RvbUhvb2tzLmpzIl0sIm5hbWVzIjpbIkNvbXBvbmVudCIsInRoZW1lIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBU0E7O0FBQ0E7Ozs7QUFWQTs7Ozs7Ozs7QUFZTyxTQUFTQSxTQUFULEdBQXFCO0FBQzFCLFFBQU1DLEtBQUssR0FBRyx3QkFBZDtBQUVBLHNCQUFPLHFEQUFhQSxLQUFiLENBQVA7QUFDRCIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ29weXJpZ2h0IChjKSBGYWNlYm9vaywgSW5jLiBhbmQgaXRzIGFmZmlsaWF0ZXMuXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKlxuICogQGZsb3dcbiAqL1xuXG5pbXBvcnQgUmVhY3QgZnJvbSAncmVhY3QnO1xuaW1wb3J0IHVzZVRoZW1lIGZyb20gJy4vdXNlVGhlbWUnO1xuXG5leHBvcnQgZnVuY3Rpb24gQ29tcG9uZW50KCkge1xuICBjb25zdCB0aGVtZSA9IHVzZVRoZW1lKCk7XG5cbiAgcmV0dXJuIDxkaXY+dGhlbWU6IHt0aGVtZX08L2Rpdj47XG59XG4iXX0= -//# sourceURL=ComponentWithExternalCustomHooks.js \ No newline at end of file +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkNvbXBvbmVudFdpdGhFeHRlcm5hbEN1c3RvbUhvb2tzLmpzIl0sIm5hbWVzIjpbIkNvbXBvbmVudCIsInRoZW1lIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBU0E7O0FBQ0E7Ozs7QUFWQTs7Ozs7Ozs7QUFZTyxTQUFTQSxTQUFULEdBQXFCO0FBQzFCLFFBQU1DLEtBQUssR0FBRyx3QkFBZDtBQUVBLHNCQUFPLHFEQUFhQSxLQUFiLENBQVA7QUFDRCIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ29weXJpZ2h0IChjKSBGYWNlYm9vaywgSW5jLiBhbmQgaXRzIGFmZmlsaWF0ZXMuXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKlxuICogQGZsb3dcbiAqL1xuXG5pbXBvcnQgUmVhY3QgZnJvbSAncmVhY3QnO1xuaW1wb3J0IHVzZVRoZW1lIGZyb20gJy4vdXNlVGhlbWUnO1xuXG5leHBvcnQgZnVuY3Rpb24gQ29tcG9uZW50KCkge1xuICBjb25zdCB0aGVtZSA9IHVzZVRoZW1lKCk7XG5cbiAgcmV0dXJuIDxkaXY+dGhlbWU6IHt0aGVtZX08L2Rpdj47XG59XG4iXX0= \ No newline at end of file diff --git a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/inline/Example.js b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/inline/Example.js index ea6b7e4b988..1902dd97ec6 100644 --- a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/inline/Example.js +++ b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/inline/Example.js @@ -25,5 +25,4 @@ function Component() { onClick: () => setCount(count + 1) }, "Click me")); } -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkV4YW1wbGUuanMiXSwibmFtZXMiOlsiQ29tcG9uZW50IiwiY291bnQiLCJzZXRDb3VudCJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQVNBOzs7Ozs7QUFUQTs7Ozs7Ozs7QUFXTyxTQUFTQSxTQUFULEdBQXFCO0FBQzFCLFFBQU0sQ0FBQ0MsS0FBRCxFQUFRQyxRQUFSLElBQW9CLHFCQUFTLENBQVQsQ0FBMUI7QUFFQSxzQkFDRSx1REFDRSx3REFBZ0JELEtBQWhCLFdBREYsZUFFRTtBQUFRLElBQUEsT0FBTyxFQUFFLE1BQU1DLFFBQVEsQ0FBQ0QsS0FBSyxHQUFHLENBQVQ7QUFBL0IsZ0JBRkYsQ0FERjtBQU1EIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5cbmltcG9ydCBSZWFjdCwge3VzZVN0YXRlfSBmcm9tICdyZWFjdCc7XG5cbmV4cG9ydCBmdW5jdGlvbiBDb21wb25lbnQoKSB7XG4gIGNvbnN0IFtjb3VudCwgc2V0Q291bnRdID0gdXNlU3RhdGUoMCk7XG5cbiAgcmV0dXJuIChcbiAgICA8ZGl2PlxuICAgICAgPHA+WW91IGNsaWNrZWQge2NvdW50fSB0aW1lczwvcD5cbiAgICAgIDxidXR0b24gb25DbGljaz17KCkgPT4gc2V0Q291bnQoY291bnQgKyAxKX0+Q2xpY2sgbWU8L2J1dHRvbj5cbiAgICA8L2Rpdj5cbiAgKTtcbn1cbiJdfQ== -//# sourceURL=Example.js \ No newline at end of file +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkV4YW1wbGUuanMiXSwibmFtZXMiOlsiQ29tcG9uZW50IiwiY291bnQiLCJzZXRDb3VudCJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQVNBOzs7Ozs7QUFUQTs7Ozs7Ozs7QUFXTyxTQUFTQSxTQUFULEdBQXFCO0FBQzFCLFFBQU0sQ0FBQ0MsS0FBRCxFQUFRQyxRQUFSLElBQW9CLHFCQUFTLENBQVQsQ0FBMUI7QUFFQSxzQkFDRSx1REFDRSx3REFBZ0JELEtBQWhCLFdBREYsZUFFRTtBQUFRLElBQUEsT0FBTyxFQUFFLE1BQU1DLFFBQVEsQ0FBQ0QsS0FBSyxHQUFHLENBQVQ7QUFBL0IsZ0JBRkYsQ0FERjtBQU1EIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5cbmltcG9ydCBSZWFjdCwge3VzZVN0YXRlfSBmcm9tICdyZWFjdCc7XG5cbmV4cG9ydCBmdW5jdGlvbiBDb21wb25lbnQoKSB7XG4gIGNvbnN0IFtjb3VudCwgc2V0Q291bnRdID0gdXNlU3RhdGUoMCk7XG5cbiAgcmV0dXJuIChcbiAgICA8ZGl2PlxuICAgICAgPHA+WW91IGNsaWNrZWQge2NvdW50fSB0aW1lczwvcD5cbiAgICAgIDxidXR0b24gb25DbGljaz17KCkgPT4gc2V0Q291bnQoY291bnQgKyAxKX0+Q2xpY2sgbWU8L2J1dHRvbj5cbiAgICA8L2Rpdj5cbiAgKTtcbn1cbiJdfQ== \ No newline at end of file diff --git a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/inline/InlineRequire.js b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/inline/InlineRequire.js index 3492fe27327..83458fd428f 100644 --- a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/inline/InlineRequire.js +++ b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/inline/InlineRequire.js @@ -18,5 +18,4 @@ function Component() { return count; } -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIklubGluZVJlcXVpcmUuanMiXSwibmFtZXMiOlsiQ29tcG9uZW50IiwiY291bnQiLCJyZXF1aXJlIiwidXNlU3RhdGUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7Ozs7Ozs7QUFTTyxTQUFTQSxTQUFULEdBQXFCO0FBQzFCLFFBQU0sQ0FBQ0MsS0FBRCxJQUFVQyxPQUFPLENBQUMsT0FBRCxDQUFQLENBQWlCQyxRQUFqQixDQUEwQixDQUExQixDQUFoQjs7QUFFQSxTQUFPRixLQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIENvbXBvbmVudCgpIHtcbiAgY29uc3QgW2NvdW50XSA9IHJlcXVpcmUoJ3JlYWN0JykudXNlU3RhdGUoMCk7XG5cbiAgcmV0dXJuIGNvdW50O1xufVxuIl19 -//# sourceURL=InlineRequire.js \ No newline at end of file +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIklubGluZVJlcXVpcmUuanMiXSwibmFtZXMiOlsiQ29tcG9uZW50IiwiY291bnQiLCJyZXF1aXJlIiwidXNlU3RhdGUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTs7Ozs7Ozs7QUFTTyxTQUFTQSxTQUFULEdBQXFCO0FBQzFCLFFBQU0sQ0FBQ0MsS0FBRCxJQUFVQyxPQUFPLENBQUMsT0FBRCxDQUFQLENBQWlCQyxRQUFqQixDQUEwQixDQUExQixDQUFoQjs7QUFFQSxTQUFPRixLQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIENvbXBvbmVudCgpIHtcbiAgY29uc3QgW2NvdW50XSA9IHJlcXVpcmUoJ3JlYWN0JykudXNlU3RhdGUoMCk7XG5cbiAgcmV0dXJuIGNvdW50O1xufVxuIl19 \ No newline at end of file diff --git a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/inline/ToDoList.js b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/inline/ToDoList.js index b196f598b6d..a5a2b216cf7 100644 --- a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/inline/ToDoList.js +++ b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/inline/ToDoList.js @@ -103,5 +103,4 @@ function List(props) { toggleItem: toggleItem })))); } -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIlRvRG9MaXN0LmpzIl0sIm5hbWVzIjpbIkxpc3RJdGVtIiwiaXRlbSIsInJlbW92ZUl0ZW0iLCJ0b2dnbGVJdGVtIiwiaGFuZGxlRGVsZXRlIiwiaGFuZGxlVG9nZ2xlIiwiaXNDb21wbGV0ZSIsInRleHQiLCJMaXN0IiwicHJvcHMiLCJuZXdJdGVtVGV4dCIsInNldE5ld0l0ZW1UZXh0IiwiaXRlbXMiLCJzZXRJdGVtcyIsImlkIiwidWlkIiwic2V0VUlEIiwiaGFuZGxlQ2xpY2siLCJoYW5kbGVLZXlQcmVzcyIsImV2ZW50Iiwia2V5IiwiaGFuZGxlQ2hhbmdlIiwiY3VycmVudFRhcmdldCIsInZhbHVlIiwiaXRlbVRvUmVtb3ZlIiwiZmlsdGVyIiwiaXRlbVRvVG9nZ2xlIiwiaW5kZXgiLCJmaW5kSW5kZXgiLCJzbGljZSIsImNvbmNhdCIsIm1hcCJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUFTQTs7Ozs7O0FBVEE7Ozs7Ozs7O0FBWU8sU0FBU0EsUUFBVCxDQUFrQjtBQUFDQyxFQUFBQSxJQUFEO0FBQU9DLEVBQUFBLFVBQVA7QUFBbUJDLEVBQUFBO0FBQW5CLENBQWxCLEVBQWtEO0FBQ3ZELFFBQU1DLFlBQVksR0FBRyx1QkFBWSxNQUFNO0FBQ3JDRixJQUFBQSxVQUFVLENBQUNELElBQUQsQ0FBVjtBQUNELEdBRm9CLEVBRWxCLENBQUNBLElBQUQsRUFBT0MsVUFBUCxDQUZrQixDQUFyQjtBQUlBLFFBQU1HLFlBQVksR0FBRyx1QkFBWSxNQUFNO0FBQ3JDRixJQUFBQSxVQUFVLENBQUNGLElBQUQsQ0FBVjtBQUNELEdBRm9CLEVBRWxCLENBQUNBLElBQUQsRUFBT0UsVUFBUCxDQUZrQixDQUFyQjtBQUlBLHNCQUNFLDZDQUNFO0FBQVEsSUFBQSxPQUFPLEVBQUVDO0FBQWpCLGNBREYsZUFFRSxnREFDRTtBQUNFLElBQUEsT0FBTyxFQUFFSCxJQUFJLENBQUNLLFVBRGhCO0FBRUUsSUFBQSxRQUFRLEVBQUVELFlBRlo7QUFHRSxJQUFBLElBQUksRUFB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UDtBQUVFLElBQUEsV0FBVyxFQUFDLGtCQUZkO0FBR0UsSUFBQSxLQUFLLEVBQUVGLFdBSFQ7QUFJRSxJQUFBLFFBQVEsRUFBRVcsWUFKWjtBQUtFLElBQUEsVUFBVSxFQUFFSDtBQUxkLElBRkYsZUFTRTtBQUFRLElBQUEsUUFBUSxFQUFFUixXQUFXLEtBQUssRUFBbEM7QUFBc0MsSUFBQSxPQUFPLEVBQUVPO0FBQS9DLGtCQUNFO0FBQU0sSUFBQSxJQUFJLEVBQUMsS0FBWDtBQUFpQixrQkFBVztBQUE1QixXQURGLENBVEYsZUFjRSxnQ0FDR0wsS0FBSyxDQUFDbUIsR0FBTixDQUFVOUIsSUFBSSxpQkFDYixvQkFBQyxRQUFEO0FBQ0UsSUFBQSxHQUFHLEVBQUVBLElBQUksQ0FBQ2EsRUFEWjtBQUVFLElBQUEsSUFBSSxFQUFFYixJQUZSO0FBR0UsSUFBQSxVQUFVLEVBQUVDLFVBSGQ7QUFJRSxJQUFBLFVBQVUsRUFBRUM7QUFKZCxJQURELENBREgsQ0FkRixDQURGO0FBMkJEIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5cbmltcG9ydCAqIGFzIFJlYWN0IGZyb20gJ3JlYWN0JztcbmltcG9ydCB7RnJhZ21lbnQsIHVzZUNhbGxiYWNrLCB1c2VTdGF0ZX0gZnJvbSAncmVhY3QnO1xuXG5leHBvcnQgZnVuY3Rpb24gTGlzdEl0ZW0oe2l0ZW0sIHJlbW92ZUl0ZW0sIHRvZ2dsZUl0ZW19KSB7XG4gIGNvbnN0IGhhbmRsZURlbGV0ZSA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICByZW1vdmVJdGVtKGl0ZW0pO1xuICB9LCBbaXRlbSwgcmVtb3ZlSXRlbV0pO1xuXG4gIGNvbnN0IGhhbmRsZVRvZ2dsZSA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICB0b2dnbGVJdGVtKGl0ZW0pO1xuICB9LCBbaXRlbSwgdG9nZ2xlSXRlbV0pO1xuXG4gIHJldHVybiAoXG4gICAgPGxpPlxuICAgICAgPGJ1dHRvbiBvbkNsaWNrPXtoYW5kbGVEZWxldGV9PkRlbGV0ZTwvYnV0dG9uPlxuICAgICAgPGxhYmVsPlxuICAgICAgICA8aW5wdXRcbiAgICAgICAgICBjaGVja2VkPXtpdGVtLmlzQ29tcGxldGV9XG4gICAgICAgICAgb25DaGFuZ2U9e2hhbmRsZVRvZ2dsZX1cbiAgICAgICAgICB0eXBlPVwiY2hlY2tib3hcIlxuICAgICAgICAvPnsnICd9XG4gICAgICAgIHtpdGVtLnRleHR9XG4gICAgICA8L2xhYmVsPlxuICAgIDwvbGk+XG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBMaXN0KHByb3BzKSB7XG4gIGNvbnN0IFtuZXdJdGVtVGV4dCwgc2V0TmV3SXRlbVRleHRdID0gdXNlU3RhdGUoJycpO1xuICBjb25zdCBbaXRlbXMsIHNldEl0ZW1zXSA9IHVzZVN0YXRlKFtcbiAgICB7aWQ6IDEsIGlzQ29tcGxldGU6IHRydWUsIHRleHQ6ICdGaXJzdCd9LFxuICAgIHtpZDogMiwgaXNDb21wbGV0ZTogdHJ1ZSwgdGV4dDogJ1NlY29uZCd9LFxuICAgIHtpZDogMywgaXNDb21wbGV0ZTogZmFsc2UsIHRleHQ6ICdUaGlyZCd9LFxuICBdKTtcbiAgY29uc3QgW3VpZCwgc2V0VUlEXSA9IHVzZVN0YXRlKDQpO1xuXG4gIGNvbnN0IGhhbmRsZUNsaWNrID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgIGlmIChuZXdJdGVtVGV4dCAhPT0gJycpIHtcbiAgICAgIHNldEl0ZW1zKFtcbiAgICAgICAgLi4uaXRlbXMsXG4gICAgICAgIHtcbiAgICAgICAgICBpZDogdWlkLFxuICAgICAgICAgIGlzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgICAgIHRleHQ6IG5ld0l0ZW1UZXh0LFxuICAgICAgICB9LFxuICAgICAgXSk7XG4gICAgICBzZXRVSUQodWlkICsgMSk7XG4gICAgICBzZXROZXdJdGVtVGV4dCgnJyk7XG4gICAgfVxuICB9LCBbbmV3SXRlbVRleHQsIGl0ZW1zLCB1aWRdKTtcblxuICBjb25zdCBoYW5kbGVLZXlQcmVzcyA9IHVzZUNhbGxiYWNrKFxuICAgIGV2ZW50ID0+IHtcbiAgICAgIGlmIChldmVudC5rZXkgPT09ICdFbnRlcicpIHtcbiAgICAgICAgaGFuZGxlQ2xpY2soKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIFtoYW5kbGVDbGlja10sXG4gICk7XG5cbiAgY29uc3QgaGFuZGxlQ2hhbmdlID0gdXNlQ2FsbGJhY2soXG4gICAgZXZlbnQgPT4ge1xuICAgICAgc2V0TmV3SXRlbVRleHQoZXZlbnQuY3VycmVudFRhcmdldC52YWx1ZSk7XG4gICAgfSxcbiAgICBbc2V0TmV3SXRlbVRleHRdLFxuICApO1xuXG4gIGNvbnN0IHJlbW92ZUl0ZW0gPSB1c2VDYWxsYmFjayhcbiAgICBpdGVtVG9SZW1vdmUgPT4gc2V0SXRlbXMoaXRlbXMuZmlsdGVyKGl0ZW0gPT4gaXRlbSAhPT0gaXRlbVRvUmVtb3ZlKSksXG4gICAgW2l0ZW1zXSxcbiAgKTtcblxuICBjb25zdCB0b2dnbGVJdGVtID0gdXNlQ2FsbGJhY2soXG4gICAgaXRlbVRvVG9nZ2xlID0+IHtcbiAgICAgIC8vIERvbnQgdXNlIGluZGV4T2YoKVxuICAgICAgLy8gYmVjYXVzZSBlZGl0aW5nIHByb3BzIGluIERldlRvb2xzIGNyZWF0ZXMgYSBuZXcgT2JqZWN0LlxuICAgICAgY29uc3QgaW5kZXggPSBpdGVtcy5maW5kSW5kZXgoaXRlbSA9PiBpdGVtLmlkID09PSBpdGVtVG9Ub2dnbGUuaWQpO1xuXG4gICAgICBzZXRJdGVtcyhcbiAgICAgICAgaXRlbXNcbiAgICAgICAgICAuc2xpY2UoMCwgaW5kZXgpXG4gICAgICAgICAgLmNvbmNhdCh7XG4gICAgICAgICAgICAuLi5pdGVtVG9Ub2dnbGUsXG4gICAgICAgICAgICBpc0NvbXBsZXRlOiAhaXRlbVRvVG9nZ2xlLmlzQ29tcGxldGUsXG4gICAgICAgICAgfSlcbiAgICAgICAgICAuY29uY2F0KGl0ZW1zLnNsaWNlKGluZGV4ICsgMSkpLFxuICAgICAgKTtcbiAgICB9LFxuICAgIFtpdGVtc10sXG4gICk7XG5cbiAgcmV0dXJuIChcbiAgICA8RnJhZ21lbnQ+XG4gICAgICA8aDE+TGlzdDwvaDE+XG4gICAgICA8aW5wdXRcbiAgICAgICAgdHlwZT1cInRleHRcIlxuICAgICAgICBwbGFjZWhvbGRlcj1cIk5ldyBsaXN0IGl0ZW0uLi5cIlxuICAgICAgICB2YWx1ZT17bmV3SXRlbVRleHR9XG4gICAgICAgIG9uQ2hhbmdlPXtoYW5kbGVDaGFuZ2V9XG4gICAgICAgIG9uS2V5UHJlc3M9e2hhbmRsZUtleVByZXNzfVxuICAgICAgLz5cbiAgICAgIDxidXR0b24gZGlzYWJsZWQ9e25ld0l0ZW1UZXh0ID09PSAnJ30gb25DbGljaz17aGFuZGxlQ2xpY2t9PlxuICAgICAgICA8c3BhbiByb2xlPVwiaW1nXCIgYXJpYS1sYWJlbD1cIkFkZCBpdGVtXCI+XG4gICAgICAgICAgQWRkXG4gICAgICAgIDwvc3Bhbj5cbiAgICAgIDwvYnV0dG9uPlxuICAgICAgPHVsPlxuICAgICAgICB7aXRlbXMubWFwKGl0ZW0gPT4gKFxuICAgICAgICAgIDxMaXN0SXRlbVxuICAgICAgICAgICAga2V5PXtpdGVtLmlkfVxuICAgICAgICAgICAgaXRlbT17aXRlbX1cbiAgICAgICAgICAgIHJlbW92ZUl0ZW09e3JlbW92ZUl0ZW19XG4gICAgICAgICAgICB0b2dnbGVJdGVtPXt0b2dnbGVJdGVtfVxuICAgICAgICAgIC8+XG4gICAgICAgICkpfVxuICAgICAgPC91bD5cbiAgICA8L0ZyYWdtZW50PlxuICApO1xufVxuIl19 -//# sourceURL=ToDoList.js \ No newline at end of file +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIlRvRG9MaXN0LmpzIl0sIm5hbWVzIjpbIkxpc3RJdGVtIiwiaXRlbSIsInJlbW92ZUl0ZW0iLCJ0b2dnbGVJdGVtIiwiaGFuZGxlRGVsZXRlIiwiaGFuZGxlVG9nZ2xlIiwiaXNDb21wbGV0ZSIsInRleHQiLCJMaXN0IiwicHJvcHMiLCJuZXdJdGVtVGV4dCIsInNldE5ld0l0ZW1UZXh0IiwiaXRlbXMiLCJzZXRJdGVtcyIsImlkIiwidWlkIiwic2V0VUlEIiwiaGFuZGxlQ2xpY2siLCJoYW5kbGVLZXlQcmVzcyIsImV2ZW50Iiwia2V5IiwiaGFuZGxlQ2hhbmdlIiwiY3VycmVudFRhcmdldCIsInZhbHVlIiwiaXRlbVRvUmVtb3ZlIiwiZmlsdGVyIiwiaXRlbVRvVG9nZ2xlIiwiaW5kZXgiLCJmaW5kSW5kZXgiLCJzbGljZSIsImNvbmNhdCIsIm1hcCJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUFTQTs7Ozs7O0FBVEE7Ozs7Ozs7O0FBWU8sU0FBU0EsUUFBVCxDQUFrQjtBQUFDQyxFQUFBQSxJQUFEO0FBQU9DLEVBQUFBLFVBQVA7QUFBbUJDLEVBQUFBO0FBQW5CLENBQWxCLEVBQWtEO0FBQ3ZELFFBQU1DLFlBQVksR0FBRyx1QkFBWSxNQUFNO0FBQ3JDRixJQUFBQSxVQUFVLENBQUNELElBQUQsQ0FBVjtBQUNELEdBRm9CLEVBRWxCLENBQUNBLElBQUQsRUFBT0MsVUFBUCxDQUZrQixDQUFyQjtBQUlBLFFBQU1HLFlBQVksR0FBRyx1QkFBWSxNQUFNO0FBQ3JDRixJQUFBQSxVQUFVLENBQUNGLElBQUQsQ0FBVjtBQUNELEdBRm9CLEVBRWxCLENBQUNBLElBQUQsRUFBT0UsVUFBUCxDQUZrQixDQUFyQjtBQUlBLHNCQUNFLDZDQUNFO0FBQVEsSUFBQSxPQUFPLEVBQUVDO0FBQWpCLGNBREYsZUFFRSxnREFDRTtBQUNFLElBQUEsT0FBTyxFQUFFSCxJQUFJLENBQUNLLFVBRGhCO0FBRUUsSUFBQSxRQUFRLEVBQUVELFlBRlo7QUFHRSxJQUFBLElBQUksRUFBQztBQUhQLElBREYsRUFLSyxHQUxMLEVBTUdKLElBQUksQ0FBQ00sSUFOUixDQUZGLENBREY7QUFhRDs7QUFFTSxTQUFTQyxJQUFULENBQWNDLEtBQWQsRUFBcUI7QUFDMUIsUUFBTSxDQUFDQyxXQUFELEVBQWNDLGNBQWQsSUFBZ0Msb0JBQVMsRUFBVCxDQUF0QztBQUNBLFFBQU0sQ0FBQ0MsS0FBRCxFQUFRQyxRQUFSLElBQW9CLG9CQUFTLENBQ2pDO0FBQUNDLElBQUFBLEVBQUUsRUFBRSxDQUFMO0FBQVFSLElBQUFBLFVBQVUsRUFBRSxJQUFwQjtBQUEwQkMsSUFBQUEsSUFBSSxFQUFFO0FBQWhDLEdBRGlDLEVBRWpDO0FBQUNPLElBQUFBLEVBQUUsRUFBRSxDQUFMO0FBQVFSLElBQUFBLFVBQVUsRUFBRSxJQUFwQjtBQUEwQkMsSUFBQUEsSUFBSSxFQUFFO0FBQWhDLEdBRmlDLEVBR2pDO0FBQUNPLElBQUFBLEVBQUUsRUFBRSxDQUFMO0FBQVFSLElBQUFBLFVBQVUsRUFBRSxLQUFwQjtBQUEyQkMsSUFBQUEsSUFBSSxFQUFFO0FBQWpDLEdBSGlDLENBQVQsQ0FBMUI7QUFLQSxRQUFNLENBQUNRLEdBQUQsRUFBTUMsTUFBTixJQUFnQixvQkFBUyxDQUFULENBQXRCO0FBRUEsUUFBTUMsV0FBVyxHQUFHLHVCQUFZLE1BQU07QUFDcEMsUUFBSVAsV0FBVyxLQUFLLEVBQXBCLEVBQXdCO0FBQ3RCRyxNQUFBQSxRQUFRLENBQUMsQ0FDUCxHQUFHRCxLQURJLEVBRVA7QUFDRUUsUUFBQUEsRUFBRSxFQUFFQyxHQUROO0FBRUVULFFBQUFBLFVBQVUsRUFBRSxLQUZkO0FBR0VDLFFBQUFBLElBQUksRUFBRUc7QUFIUixPQUZPLENBQUQsQ0FBUjtBQVFBTSxNQUFBQSxNQUFNLENBQUNELEdBQUcsR0FBRyxDQUFQLENBQU47QUFDQUosTUFBQUEsY0FBYyxDQUFDLEVBQUQsQ0FBZDtBQUNEO0FBQ0YsR0FibUIsRUFhakIsQ0FBQ0QsV0FBRCxFQUFjRSxLQUFkLEVBQXFCRyxHQUFyQixDQWJpQixDQUFwQjtBQWVBLFFBQU1HLGNBQWMsR0FBRyx1QkFDckJDLEtBQUssSUFBSTtBQUNQLFFBQUlBLEtBQUssQ0FBQ0MsR0FBTixLQUFjLE9BQWxCLEVBQTJCO0FBQ3pCSCxNQUFBQSxXQUFXO0FBQ1o7QUFDRixHQUxvQixFQU1yQixDQUFDQSxXQUFELENBTnFCLENBQXZCO0FBU0EsUUFBTUksWUFBWSxHQUFHLHVCQUNuQkYsS0FBSyxJQUFJO0FBQ1BSLElBQUFBLGNBQWMsQ0FBQ1EsS0FBSyxDQUFDRyxhQUFOLENBQW9CQyxLQUFyQixDQUFkO0FBQ0QsR0FIa0IsRUFJbkIsQ0FBQ1osY0FBRCxDQUptQixDQUFyQjtBQU9BLFFBQU1ULFVBQVUsR0FBRyx1QkFDakJzQixZQUFZLElBQUlYLFFBQVEsQ0FBQ0QsS0FBSyxDQUFDYSxNQUFOLENBQWF4QixJQUFJLElBQUlBLElBQUksS0FBS3VCLFlBQTlCLENBQUQsQ0FEUCxFQUVqQixDQUFDWixLQUFELENBRmlCLENBQW5CO0FBS0EsUUFBTVQsVUFBVSxHQUFHLHVCQUNqQnVCLFlBQVksSUFBSTtBQUNkO0FBQ0E7QUFDQSxVQUFNQyxLQUFLLEdBQUdmLEtBQUssQ0FBQ2dCLFNBQU4sQ0FBZ0IzQixJQUFJLElBQUlBLElBQUksQ0FBQ2EsRUFBTCxLQUFZWSxZQUFZLENBQUNaLEVBQWpELENBQWQ7QUFFQUQsSUFBQUEsUUFBUSxDQUNORCxLQUFLLENBQ0ZpQixLQURILENBQ1MsQ0FEVCxFQUNZRixLQURaLEVBRUdHLE1BRkgsQ0FFVSxFQUNOLEdBQUdKLFlBREc7QUFFTnBCLE1BQUFBLFVBQVUsRUFBRSxDQUFDb0IsWUFBWSxDQUFDcEI7QUFGcEIsS0FGVixFQU1Hd0IsTUFOSCxDQU1VbEIsS0FBSyxDQUFDaUIsS0FBTixDQUFZRixLQUFLLEdBQUcsQ0FBcEIsQ0FOVixDQURNLENBQVI7QUFTRCxHQWZnQixFQWdCakIsQ0FBQ2YsS0FBRCxDQWhCaUIsQ0FBbkI7QUFtQkEsc0JBQ0Usb0JBQUMsY0FBRCxxQkFDRSx1Q0FERixlQUVFO0FBQ0UsSUFBQSxJQUFJLEVBQUMsTUFEUDtBQUVFLElBQUEsV0FBVyxFQUFDLGtCQUZkO0FBR0UsSUFBQSxLQUFLLEVBQUVGLFdBSFQ7QUFJRSxJQUFBLFFBQVEsRUFBRVcsWUFKWjtBQUtFLElBQUEsVUFBVSxFQUFFSDtBQUxkLElBRkYsZUFTRTtBQUFRLElBQUEsUUFBUSxFQUFFUixXQUFXLEtBQUssRUFBbEM7QUFBc0MsSUFBQSxPQUFPLEVBQUVPO0FBQS9DLGtCQUNFO0FBQU0sSUFBQSxJQUFJLEVBQUMsS0FBWDtBQUFpQixrQkFBVztBQUE1QixXQURGLENBVEYsZUFjRSxnQ0FDR0wsS0FBSyxDQUFDbUIsR0FBTixDQUFVOUIsSUFBSSxpQkFDYixvQkFBQyxRQUFEO0FBQ0UsSUFBQSxHQUFHLEVBQUVBLElBQUksQ0FBQ2EsRUFEWjtBQUVFLElBQUEsSUFBSSxFQUFFYixJQUZSO0FBR0UsSUFBQSxVQUFVLEVBQUVDLFVBSGQ7QUFJRSxJQUFBLFVBQVUsRUFBRUM7QUFKZCxJQURELENBREgsQ0FkRixDQURGO0FBMkJEIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5cbmltcG9ydCAqIGFzIFJlYWN0IGZyb20gJ3JlYWN0JztcbmltcG9ydCB7RnJhZ21lbnQsIHVzZUNhbGxiYWNrLCB1c2VTdGF0ZX0gZnJvbSAncmVhY3QnO1xuXG5leHBvcnQgZnVuY3Rpb24gTGlzdEl0ZW0oe2l0ZW0sIHJlbW92ZUl0ZW0sIHRvZ2dsZUl0ZW19KSB7XG4gIGNvbnN0IGhhbmRsZURlbGV0ZSA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICByZW1vdmVJdGVtKGl0ZW0pO1xuICB9LCBbaXRlbSwgcmVtb3ZlSXRlbV0pO1xuXG4gIGNvbnN0IGhhbmRsZVRvZ2dsZSA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICB0b2dnbGVJdGVtKGl0ZW0pO1xuICB9LCBbaXRlbSwgdG9nZ2xlSXRlbV0pO1xuXG4gIHJldHVybiAoXG4gICAgPGxpPlxuICAgICAgPGJ1dHRvbiBvbkNsaWNrPXtoYW5kbGVEZWxldGV9PkRlbGV0ZTwvYnV0dG9uPlxuICAgICAgPGxhYmVsPlxuICAgICAgICA8aW5wdXRcbiAgICAgICAgICBjaGVja2VkPXtpdGVtLmlzQ29tcGxldGV9XG4gICAgICAgICAgb25DaGFuZ2U9e2hhbmRsZVRvZ2dsZX1cbiAgICAgICAgICB0eXBlPVwiY2hlY2tib3hcIlxuICAgICAgICAvPnsnICd9XG4gICAgICAgIHtpdGVtLnRleHR9XG4gICAgICA8L2xhYmVsPlxuICAgIDwvbGk+XG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBMaXN0KHByb3BzKSB7XG4gIGNvbnN0IFtuZXdJdGVtVGV4dCwgc2V0TmV3SXRlbVRleHRdID0gdXNlU3RhdGUoJycpO1xuICBjb25zdCBbaXRlbXMsIHNldEl0ZW1zXSA9IHVzZVN0YXRlKFtcbiAgICB7aWQ6IDEsIGlzQ29tcGxldGU6IHRydWUsIHRleHQ6ICdGaXJzdCd9LFxuICAgIHtpZDogMiwgaXNDb21wbGV0ZTogdHJ1ZSwgdGV4dDogJ1NlY29uZCd9LFxuICAgIHtpZDogMywgaXNDb21wbGV0ZTogZmFsc2UsIHRleHQ6ICdUaGlyZCd9LFxuICBdKTtcbiAgY29uc3QgW3VpZCwgc2V0VUlEXSA9IHVzZVN0YXRlKDQpO1xuXG4gIGNvbnN0IGhhbmRsZUNsaWNrID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgIGlmIChuZXdJdGVtVGV4dCAhPT0gJycpIHtcbiAgICAgIHNldEl0ZW1zKFtcbiAgICAgICAgLi4uaXRlbXMsXG4gICAgICAgIHtcbiAgICAgICAgICBpZDogdWlkLFxuICAgICAgICAgIGlzQ29tcGxldGU6IGZhbHNlLFxuICAgICAgICAgIHRleHQ6IG5ld0l0ZW1UZXh0LFxuICAgICAgICB9LFxuICAgICAgXSk7XG4gICAgICBzZXRVSUQodWlkICsgMSk7XG4gICAgICBzZXROZXdJdGVtVGV4dCgnJyk7XG4gICAgfVxuICB9LCBbbmV3SXRlbVRleHQsIGl0ZW1zLCB1aWRdKTtcblxuICBjb25zdCBoYW5kbGVLZXlQcmVzcyA9IHVzZUNhbGxiYWNrKFxuICAgIGV2ZW50ID0+IHtcbiAgICAgIGlmIChldmVudC5rZXkgPT09ICdFbnRlcicpIHtcbiAgICAgICAgaGFuZGxlQ2xpY2soKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIFtoYW5kbGVDbGlja10sXG4gICk7XG5cbiAgY29uc3QgaGFuZGxlQ2hhbmdlID0gdXNlQ2FsbGJhY2soXG4gICAgZXZlbnQgPT4ge1xuICAgICAgc2V0TmV3SXRlbVRleHQoZXZlbnQuY3VycmVudFRhcmdldC52YWx1ZSk7XG4gICAgfSxcbiAgICBbc2V0TmV3SXRlbVRleHRdLFxuICApO1xuXG4gIGNvbnN0IHJlbW92ZUl0ZW0gPSB1c2VDYWxsYmFjayhcbiAgICBpdGVtVG9SZW1vdmUgPT4gc2V0SXRlbXMoaXRlbXMuZmlsdGVyKGl0ZW0gPT4gaXRlbSAhPT0gaXRlbVRvUmVtb3ZlKSksXG4gICAgW2l0ZW1zXSxcbiAgKTtcblxuICBjb25zdCB0b2dnbGVJdGVtID0gdXNlQ2FsbGJhY2soXG4gICAgaXRlbVRvVG9nZ2xlID0+IHtcbiAgICAgIC8vIERvbnQgdXNlIGluZGV4T2YoKVxuICAgICAgLy8gYmVjYXVzZSBlZGl0aW5nIHByb3BzIGluIERldlRvb2xzIGNyZWF0ZXMgYSBuZXcgT2JqZWN0LlxuICAgICAgY29uc3QgaW5kZXggPSBpdGVtcy5maW5kSW5kZXgoaXRlbSA9PiBpdGVtLmlkID09PSBpdGVtVG9Ub2dnbGUuaWQpO1xuXG4gICAgICBzZXRJdGVtcyhcbiAgICAgICAgaXRlbXNcbiAgICAgICAgICAuc2xpY2UoMCwgaW5kZXgpXG4gICAgICAgICAgLmNvbmNhdCh7XG4gICAgICAgICAgICAuLi5pdGVtVG9Ub2dnbGUsXG4gICAgICAgICAgICBpc0NvbXBsZXRlOiAhaXRlbVRvVG9nZ2xlLmlzQ29tcGxldGUsXG4gICAgICAgICAgfSlcbiAgICAgICAgICAuY29uY2F0KGl0ZW1zLnNsaWNlKGluZGV4ICsgMSkpLFxuICAgICAgKTtcbiAgICB9LFxuICAgIFtpdGVtc10sXG4gICk7XG5cbiAgcmV0dXJuIChcbiAgICA8RnJhZ21lbnQ+XG4gICAgICA8aDE+TGlzdDwvaDE+XG4gICAgICA8aW5wdXRcbiAgICAgICAgdHlwZT1cInRleHRcIlxuICAgICAgICBwbGFjZWhvbGRlcj1cIk5ldyBsaXN0IGl0ZW0uLi5cIlxuICAgICAgICB2YWx1ZT17bmV3SXRlbVRleHR9XG4gICAgICAgIG9uQ2hhbmdlPXtoYW5kbGVDaGFuZ2V9XG4gICAgICAgIG9uS2V5UHJlc3M9e2hhbmRsZUtleVByZXNzfVxuICAgICAgLz5cbiAgICAgIDxidXR0b24gZGlzYWJsZWQ9e25ld0l0ZW1UZXh0ID09PSAnJ30gb25DbGljaz17aGFuZGxlQ2xpY2t9PlxuICAgICAgICA8c3BhbiByb2xlPVwiaW1nXCIgYXJpYS1sYWJlbD1cIkFkZCBpdGVtXCI+XG4gICAgICAgICAgQWRkXG4gICAgICAgIDwvc3Bhbj5cbiAgICAgIDwvYnV0dG9uPlxuICAgICAgPHVsPlxuICAgICAgICB7aXRlbXMubWFwKGl0ZW0gPT4gKFxuICAgICAgICAgIDxMaXN0SXRlbVxuICAgICAgICAgICAga2V5PXtpdGVtLmlkfVxuICAgICAgICAgICAgaXRlbT17aXRlbX1cbiAgICAgICAgICAgIHJlbW92ZUl0ZW09e3JlbW92ZUl0ZW19XG4gICAgICAgICAgICB0b2dnbGVJdGVtPXt0b2dnbGVJdGVtfVxuICAgICAgICAgIC8+XG4gICAgICAgICkpfVxuICAgICAgPC91bD5cbiAgICA8L0ZyYWdtZW50PlxuICApO1xufVxuIl19 \ No newline at end of file diff --git a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/inline/index.js b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/inline/index.js new file mode 100644 index 00000000000..429ebfbbcf6 --- /dev/null +++ b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/inline/index.js @@ -0,0 +1,57 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "ComponentWithCustomHook", { + enumerable: true, + get: function () { + return _ComponentWithCustomHook.Component; + } +}); +Object.defineProperty(exports, "ComponentWithExternalCustomHooks", { + enumerable: true, + get: function () { + return _ComponentWithExternalCustomHooks.Component; + } +}); +Object.defineProperty(exports, "Example", { + enumerable: true, + get: function () { + return _Example.Component; + } +}); +Object.defineProperty(exports, "InlineRequire", { + enumerable: true, + get: function () { + return _InlineRequire.Component; + } +}); +Object.defineProperty(exports, "useTheme", { + enumerable: true, + get: function () { + return _useTheme.default; + } +}); +exports.ToDoList = void 0; + +var _ComponentWithCustomHook = require("./ComponentWithCustomHook"); + +var _ComponentWithExternalCustomHooks = require("./ComponentWithExternalCustomHooks"); + +var _Example = require("./Example"); + +var _InlineRequire = require("./InlineRequire"); + +var ToDoList = _interopRequireWildcard(require("./ToDoList")); + +exports.ToDoList = ToDoList; + +var _useTheme = _interopRequireDefault(require("./useTheme")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; } + +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; } +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImluZGV4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFTQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7OztBQUVBIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIEZhY2Vib29rLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy5cbiAqXG4gKiBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGVcbiAqIExJQ0VOU0UgZmlsZSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBzb3VyY2UgdHJlZS5cbiAqXG4gKiBAZmxvd1xuICovXG5cbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFdpdGhDdXN0b21Ib29rfSBmcm9tICcuL0NvbXBvbmVudFdpdGhDdXN0b21Ib29rJztcbmV4cG9ydCB7Q29tcG9uZW50IGFzIENvbXBvbmVudFdpdGhFeHRlcm5hbEN1c3RvbUhvb2tzfSBmcm9tICcuL0NvbXBvbmVudFdpdGhFeHRlcm5hbEN1c3RvbUhvb2tzJztcbmV4cG9ydCB7Q29tcG9uZW50IGFzIEV4YW1wbGV9IGZyb20gJy4vRXhhbXBsZSc7XG5leHBvcnQge0NvbXBvbmVudCBhcyBJbmxpbmVSZXF1aXJlfSBmcm9tICcuL0lubGluZVJlcXVpcmUnO1xuaW1wb3J0ICogYXMgVG9Eb0xpc3QgZnJvbSAnLi9Ub0RvTGlzdCc7XG5leHBvcnQge1RvRG9MaXN0fTtcbmV4cG9ydCB7ZGVmYXVsdCBhcyB1c2VUaGVtZX0gZnJvbSAnLi91c2VUaGVtZSc7XG4iXX0= \ No newline at end of file diff --git a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/inline/useTheme.js b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/inline/useTheme.js index 1122f6ab69e..0703c679363 100644 --- a/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/inline/useTheme.js +++ b/packages/react-devtools-extensions/src/__tests__/__source__/__compiled__/inline/useTheme.js @@ -24,5 +24,4 @@ function useTheme() { (0, _react.useDebugValue)(theme); return theme; } -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInVzZVRoZW1lLmpzIl0sIm5hbWVzIjpbIlRoZW1lQ29udGV4dCIsInVzZVRoZW1lIiwidGhlbWUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBU0E7O0FBVEE7Ozs7Ozs7O0FBV08sTUFBTUEsWUFBWSxnQkFBRywwQkFBYyxRQUFkLENBQXJCOzs7QUFFUSxTQUFTQyxRQUFULEdBQW9CO0FBQ2pDLFFBQU1DLEtBQUssR0FBRyx1QkFBV0YsWUFBWCxDQUFkO0FBQ0EsNEJBQWNFLEtBQWQ7QUFDQSxTQUFPQSxLQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IHtjcmVhdGVDb250ZXh0LCB1c2VDb250ZXh0LCB1c2VEZWJ1Z1ZhbHVlfSBmcm9tICdyZWFjdCc7XG5cbmV4cG9ydCBjb25zdCBUaGVtZUNvbnRleHQgPSBjcmVhdGVDb250ZXh0KCdicmlnaHQnKTtcblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gdXNlVGhlbWUoKSB7XG4gIGNvbnN0IHRoZW1lID0gdXNlQ29udGV4dChUaGVtZUNvbnRleHQpO1xuICB1c2VEZWJ1Z1ZhbHVlKHRoZW1lKTtcbiAgcmV0dXJuIHRoZW1lO1xufVxuIl19 -//# sourceURL=useTheme.js \ No newline at end of file +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInVzZVRoZW1lLmpzIl0sIm5hbWVzIjpbIlRoZW1lQ29udGV4dCIsInVzZVRoZW1lIiwidGhlbWUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBU0E7O0FBVEE7Ozs7Ozs7O0FBV08sTUFBTUEsWUFBWSxnQkFBRywwQkFBYyxRQUFkLENBQXJCOzs7QUFFUSxTQUFTQyxRQUFULEdBQW9CO0FBQ2pDLFFBQU1DLEtBQUssR0FBRyx1QkFBV0YsWUFBWCxDQUFkO0FBQ0EsNEJBQWNFLEtBQWQ7QUFDQSxTQUFPQSxLQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvcHlyaWdodCAoYykgRmFjZWJvb2ssIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLlxuICpcbiAqIFRoaXMgc291cmNlIGNvZGUgaXMgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlIGZvdW5kIGluIHRoZVxuICogTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLlxuICpcbiAqIEBmbG93XG4gKi9cblxuaW1wb3J0IHtjcmVhdGVDb250ZXh0LCB1c2VDb250ZXh0LCB1c2VEZWJ1Z1ZhbHVlfSBmcm9tICdyZWFjdCc7XG5cbmV4cG9ydCBjb25zdCBUaGVtZUNvbnRleHQgPSBjcmVhdGVDb250ZXh0KCdicmlnaHQnKTtcblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gdXNlVGhlbWUoKSB7XG4gIGNvbnN0IHRoZW1lID0gdXNlQ29udGV4dChUaGVtZUNvbnRleHQpO1xuICB1c2VEZWJ1Z1ZhbHVlKHRoZW1lKTtcbiAgcmV0dXJuIHRoZW1lO1xufVxuIl19 \ No newline at end of file diff --git a/packages/react-devtools-extensions/src/__tests__/__source__/index.js b/packages/react-devtools-extensions/src/__tests__/__source__/index.js new file mode 100644 index 00000000000..a4f204fe19f --- /dev/null +++ b/packages/react-devtools-extensions/src/__tests__/__source__/index.js @@ -0,0 +1,16 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ + +export {Component as ComponentWithCustomHook} from './ComponentWithCustomHook'; +export {Component as ComponentWithExternalCustomHooks} from './ComponentWithExternalCustomHooks'; +export {Component as Example} from './Example'; +export {Component as InlineRequire} from './InlineRequire'; +import * as ToDoList from './ToDoList'; +export {ToDoList}; +export {default as useTheme} from './useTheme'; diff --git a/packages/react-devtools-extensions/src/__tests__/parseHookNames-test.js b/packages/react-devtools-extensions/src/__tests__/parseHookNames-test.js index 3a65b3709d2..e1efe7c32ca 100644 --- a/packages/react-devtools-extensions/src/__tests__/parseHookNames-test.js +++ b/packages/react-devtools-extensions/src/__tests__/parseHookNames-test.js @@ -33,25 +33,18 @@ describe('parseHookNames', () => { // Jest (jest-runner?) configures Errors to automatically account for source maps. // This changes behavior between our tests and the browser. - // To "fix" this, clear the prepareStackTrace() method on the Error object. - delete Error.prepareStackTrace; + // Ideally we would clear the prepareStackTrace() method on the Error object, + // but Node falls back to looking for it on the main context's Error constructor, + // which may still be patched. + // To ensure we get the default behavior, override prepareStackTrace ourselves. + // NOTE: prepareStackTrace is called from the error.stack getter, but the getter + // has a recursion breaker which falls back to the default behavior. + Error.prepareStackTrace = (error, trace) => { + return error.stack; + }; fetchMock.mockIf(/.+$/, request => { - const {resolve} = require('path'); - const url = request.url; - if (url.endsWith('js.map')) { - // Source maps are relative URLs (e.g. "path/to/Exmaple.js" specifies "Exmaple.js.map"). - const sourceMapURL = resolve( - __dirname, - '__source__', - '__compiled__', - 'external', - url, - ); - return Promise.resolve(requireText(sourceMapURL, 'utf8')); - } else { - return Promise.resolve(requireText(url, 'utf8')); - } + return Promise.resolve(requireText(request.url, 'utf8')); }); // Mock out portion of browser API used by parseHookNames to initialize "source-map". @@ -185,10 +178,10 @@ describe('parseHookNames', () => { ]); }); - describe('inline and external source maps', () => { + describe('inline, external and bundle source maps', () => { it('should work for simple components', async () => { - async function test(path) { - const Component = require(path).Component; + async function test(path, name = 'Component') { + const Component = require(path)[name]; const hookNames = await getHookNamesForComponent(Component); expectHookNamesToEqual(hookNames, [ 'count', // useState @@ -198,11 +191,12 @@ describe('parseHookNames', () => { await test('./__source__/Example'); // original source (uncompiled) await test('./__source__/__compiled__/inline/Example'); // inline source map await test('./__source__/__compiled__/external/Example'); // external source map + await test('./__source__/__compiled__/bundle/index', 'Example'); // bundle source map }); it('should work with more complex files and components', async () => { - async function test(path) { - const components = require(path); + async function test(path, name = undefined) { + const components = name != null ? require(path)[name] : require(path); let hookNames = await getHookNamesForComponent(components.List); expectHookNamesToEqual(hookNames, [ @@ -228,11 +222,12 @@ describe('parseHookNames', () => { await test('./__source__/ToDoList'); // original source (uncompiled) await test('./__source__/__compiled__/inline/ToDoList'); // inline source map await test('./__source__/__compiled__/external/ToDoList'); // external source map + await test('./__source__/__compiled__/bundle', 'ToDoList'); // bundle source map }); it('should work for custom hook', async () => { - async function test(path) { - const Component = require(path).Component; + async function test(path, name = 'Component') { + const Component = require(path)[name]; const hookNames = await getHookNamesForComponent(Component); expectHookNamesToEqual(hookNames, [ 'count', // useState() @@ -244,11 +239,12 @@ describe('parseHookNames', () => { await test('./__source__/ComponentWithCustomHook'); // original source (uncompiled) await test('./__source__/__compiled__/inline/ComponentWithCustomHook'); // inline source map await test('./__source__/__compiled__/external/ComponentWithCustomHook'); // external source map + await test('./__source__/__compiled__/bundle', 'ComponentWithCustomHook'); // bundle source map }); it('should work for external hooks', async () => { - async function test(path) { - const Component = require(path).Component; + async function test(path, name = 'Component') { + const Component = require(path)[name]; const hookNames = await getHookNamesForComponent(Component); expectHookNamesToEqual(hookNames, [ 'theme', // useTheme() @@ -265,14 +261,18 @@ describe('parseHookNames', () => { await test( './__source__/__compiled__/external/ComponentWithExternalCustomHooks', ); // external source map + await test( + './__source__/__compiled__/bundle', + 'ComponentWithExternalCustomHooks', + ); // bundle source map }); // TODO Inline require (e.g. require("react").useState()) isn't supported yet. // Maybe this isn't an important use case to support, // since inline requires are most likely to exist in compiled source (if at all). xit('should work for inline requires', async () => { - async function test(path) { - const Component = require(path).Component; + async function test(path, name = 'Component') { + const Component = require(path)[name]; const hookNames = await getHookNamesForComponent(Component); expectHookNamesToEqual(hookNames, [ 'count', // useState() @@ -282,6 +282,7 @@ describe('parseHookNames', () => { await test('./__source__/InlineRequire'); // original source (uncompiled) await test('./__source__/__compiled__/inline/InlineRequire'); // inline source map await test('./__source__/__compiled__/external/InlineRequire'); // external source map + await test('./__source__/__compiled__/bundle', 'InlineRequire'); // bundle source map }); }); }); diff --git a/packages/react-devtools-extensions/src/__tests__/updateMockSourceMaps.js b/packages/react-devtools-extensions/src/__tests__/updateMockSourceMaps.js index 590cd36cc63..231bdee5212 100644 --- a/packages/react-devtools-extensions/src/__tests__/updateMockSourceMaps.js +++ b/packages/react-devtools-extensions/src/__tests__/updateMockSourceMaps.js @@ -9,16 +9,23 @@ const { } = require('fs'); const {emptyDirSync} = require('fs-extra'); const {resolve} = require('path'); +const rollup = require('rollup'); +const babel = require('rollup-plugin-babel'); +const commonjs = require('rollup-plugin-commonjs'); +const jsx = require('acorn-jsx'); +const rollupResolve = require('rollup-plugin-node-resolve'); const sourceDir = resolve(__dirname, '__source__'); const buildRoot = resolve(sourceDir, '__compiled__'); const externalDir = resolve(buildRoot, 'external'); const inlineDir = resolve(buildRoot, 'inline'); +const bundleDir = resolve(buildRoot, 'bundle'); // Remove previous builds emptyDirSync(buildRoot); mkdirSync(externalDir); mkdirSync(inlineDir); +mkdirSync(bundleDir); function compile(fileName) { const code = readFileSync(resolve(sourceDir, fileName), 'utf8'); @@ -44,9 +51,7 @@ function compile(fileName) { // Generate compiled output with external source maps writeFileSync( resolve(externalDir, fileName), - transformed.code + - `\n//# sourceMappingURL=${fileName}.map` + - `\n//# sourceURL=${fileName}`, + transformed.code + `\n//# sourceMappingURL=${fileName}.map`, 'utf8', ); writeFileSync( @@ -60,12 +65,32 @@ function compile(fileName) { resolve(inlineDir, fileName), transformed.code + '\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,' + - btoa(JSON.stringify(sourceMap)) + - `\n//# sourceURL=${fileName}`, + btoa(JSON.stringify(sourceMap)), 'utf8', ); } +async function bundle() { + const entryFileName = resolve(sourceDir, 'index.js'); + + // Bundle all modules with rollup + const result = await rollup.rollup({ + input: entryFileName, + acornInjectPlugins: [jsx()], + plugins: [ + rollupResolve(), + commonjs(), + babel({presets: ['@babel/preset-react'], sourceMap: true}), + ], + external: ['react'], + }); + await result.write({ + file: resolve(bundleDir, 'index.js'), + format: 'cjs', + sourcemap: true, + }); +} + // Compile all files in the current directory const entries = readdirSync(sourceDir); entries.forEach(entry => { @@ -74,3 +99,8 @@ entries.forEach(entry => { compile(entry); } }); + +bundle().catch(e => { + console.error(e); + process.exit(1); +}); diff --git a/packages/react-devtools-extensions/src/astUtils.js b/packages/react-devtools-extensions/src/astUtils.js index cc976bbd198..dff938c9d38 100644 --- a/packages/react-devtools-extensions/src/astUtils.js +++ b/packages/react-devtools-extensions/src/astUtils.js @@ -20,14 +20,6 @@ export type SourceFileASTWithHookDetails = { source: string, }; -export type SourceMap = {| - mappings: string, - names: Array, - sources: Array, - sourcesContent: Array, - version: number, -|}; - const AST_NODE_TYPES = Object.freeze({ CALL_EXPRESSION: 'CallExpression', MEMBER_EXPRESSION: 'MemberExpression', diff --git a/packages/react-devtools-extensions/src/parseHookNames.js b/packages/react-devtools-extensions/src/parseHookNames.js index f2d74dc2929..dc2b8b3c4bc 100644 --- a/packages/react-devtools-extensions/src/parseHookNames.js +++ b/packages/react-devtools-extensions/src/parseHookNames.js @@ -24,7 +24,7 @@ import type { } from 'react-debug-tools/src/ReactDebugHooks'; import type {HookNames, LRUCache} from 'react-devtools-shared/src/types'; import type {Thenable} from 'shared/ReactTypes'; -import type {SourceConsumer, SourceMap} from './astUtils'; +import type {SourceConsumer} from './astUtils'; const SOURCE_MAP_REGEX = / ?sourceMappingURL=([^\s'"]+)/gm; const ABSOLUTE_URL_REGEX = /^https?:\/\//i; @@ -43,36 +43,36 @@ type HookSourceData = {| // If no source map has been provided, this code will be the same as runtimeSourceCode. originalSourceCode: string | null, + // Original source URL if there is a source map, or the same as runtimeSourceURL. + originalSourceURL: string | null, + // Compiled code (React components or custom hooks) containing primitive hook calls. runtimeSourceCode: string | null, + // Same as hookSource.fileName but guaranteed to be non-null. + runtimeSourceURL: string, + // APIs from source-map for parsing source maps (if detected). sourceConsumer: SourceConsumer | null, // External URL of source map. // Sources without source maps (or with inline source maps) won't have this. sourceMapURL: string | null, - - // Parsed source map object. - sourceMapContents: SourceMap | null, |}; -type CachedMetadata = {| - originalSourceAST: AST, - originalSourceCode: string, +type CachedRuntimeCodeMetadata = {| sourceConsumer: SourceConsumer | null, |}; -// On large trees, encoding takes significant time. -// Try to reuse the already encoded strings. -const fileNameToMetadataCache: LRUCache = new LRU({ +const runtimeURLToMetadataCache: LRUCache< + string, + CachedRuntimeCodeMetadata, +> = new LRU({ max: 50, - dispose: (fileName: string, metadata: CachedMetadata) => { + dispose: (runtimeSourceURL: string, metadata: CachedRuntimeCodeMetadata) => { if (__DEBUG__) { console.log( - 'fileNameToHookSourceData.dispose() Evicting cached metadata for "' + - fileName + - '"', + `runtimeURLToMetadataCache.dispose() Evicting cached metadata for "${runtimeSourceURL}"`, ); } @@ -83,6 +83,36 @@ const fileNameToMetadataCache: LRUCache = new LRU({ }, }); +type CachedSourceCodeMetadata = {| + originalSourceAST: AST, + originalSourceCode: string, +|}; + +const originalURLToMetadataCache: LRUCache< + string, + CachedSourceCodeMetadata, +> = new LRU({ + max: 50, + dispose: (originalSourceURL: string, metadata: CachedSourceCodeMetadata) => { + if (__DEBUG__) { + console.log( + `originalURLToMetadataCache.dispose() Evicting cached metadata for "${originalSourceURL}"`, + ); + } + }, +}); + +function getLocationKey({ + fileName, + lineNumber, + columnNumber, +}: HookSource): string { + if (fileName == null || lineNumber == null || columnNumber == null) { + throw Error('Hook source code location not found.'); + } + return `${fileName}:${lineNumber}:${columnNumber}`; +} + export default async function parseHookNames( hooksTree: HooksTree, ): Thenable { @@ -97,8 +127,8 @@ export default async function parseHookNames( console.log('parseHookNames() hooksList:', hooksList); } - // Gather the unique set of source files to load for the built-in hooks. - const fileNameToHookSourceData: Map = new Map(); + // Create map of unique source locations (file names plus line and column numbers) to metadata about hooks. + const locationKeyToHookSourceData: Map = new Map(); for (let i = 0; i < hooksList.length; i++) { const hook = hooksList[i]; @@ -109,50 +139,47 @@ export default async function parseHookNames( throw Error('Hook source code location not found.'); } - const fileName = hookSource.fileName; - if (fileName == null) { - throw Error('Hook source code location not found.'); - } else { - if (!fileNameToHookSourceData.has(fileName)) { - const hookSourceData: HookSourceData = { - hookSource, - originalSourceAST: null, - originalSourceCode: null, - runtimeSourceCode: null, - sourceConsumer: null, - sourceMapURL: null, - sourceMapContents: null, - }; - - // If we've already loaded source/source map info for this file, - // we can skip reloading it (and more importantly, re-parsing it). - const metadata = fileNameToMetadataCache.get(fileName); - if (metadata != null) { - if (__DEBUG__) { - console.groupCollapsed( - 'parseHookNames() Found cached metadata for file "' + - fileName + - '"', - ); - console.log(metadata); - console.groupEnd(); - } - - hookSourceData.originalSourceAST = metadata.originalSourceAST; - hookSourceData.originalSourceCode = metadata.originalSourceCode; - hookSourceData.sourceConsumer = metadata.sourceConsumer; + const locationKey = getLocationKey(hookSource); + if (!locationKeyToHookSourceData.has(locationKey)) { + // Can't be null because getLocationKey() would have thrown + const runtimeSourceURL = ((hookSource.fileName: any): string); + + const hookSourceData: HookSourceData = { + hookSource, + originalSourceAST: null, + originalSourceCode: null, + originalSourceURL: null, + runtimeSourceCode: null, + runtimeSourceURL, + sourceConsumer: null, + sourceMapURL: null, + }; + + // If we've already loaded the source map info for this file, + // we can skip reloading it (and more importantly, re-parsing it). + const runtimeMetadata = runtimeURLToMetadataCache.get( + hookSourceData.runtimeSourceURL, + ); + if (runtimeMetadata != null) { + if (__DEBUG__) { + console.groupCollapsed( + `parseHookNames() Found cached runtime metadata for file "${hookSourceData.runtimeSourceURL}"`, + ); + console.log(runtimeMetadata); + console.groupEnd(); } - - fileNameToHookSourceData.set(fileName, hookSourceData); + hookSourceData.sourceConsumer = runtimeMetadata.sourceConsumer; } + + locationKeyToHookSourceData.set(locationKey, hookSourceData); } } - return loadSourceFiles(fileNameToHookSourceData) - .then(() => extractAndLoadSourceMaps(fileNameToHookSourceData)) - .then(() => parseSourceAST(fileNameToHookSourceData)) - .then(() => updateLruCache(fileNameToHookSourceData)) - .then(() => findHookNames(hooksList, fileNameToHookSourceData)); + return loadSourceFiles(locationKeyToHookSourceData) + .then(() => extractAndLoadSourceMaps(locationKeyToHookSourceData)) + .then(() => parseSourceAST(locationKeyToHookSourceData)) + .then(() => updateLruCache(locationKeyToHookSourceData)) + .then(() => findHookNames(hooksList, locationKeyToHookSourceData)); } function decodeBase64String(encoded: string): Object { @@ -170,12 +197,31 @@ function decodeBase64String(encoded: string): Object { } function extractAndLoadSourceMaps( - fileNameToHookSourceData: Map, + locationKeyToHookSourceData: Map, ): Promise<*> { - const promises = []; - fileNameToHookSourceData.forEach(hookSourceData => { - if (hookSourceData.originalSourceAST !== null) { - // Use cached metadata. + // SourceMapConsumer.initialize() does nothing when running in Node (aka Jest) + // because the wasm file is automatically read from the file system + // so we can avoid triggering a warning message about this. + if (!__TEST__) { + if (__DEBUG__) { + console.log( + 'extractAndLoadSourceMaps() Initializing source-map library ...', + ); + } + + // $FlowFixMe + const wasmMappingsURL = chrome.extension.getURL('mappings.wasm'); + + SourceMapConsumer.initialize({'lib/mappings.wasm': wasmMappingsURL}); + } + + // Deduplicate fetches, since there can be multiple location keys per source map. + const fetchPromises = new Map(); + + const setPromises = []; + locationKeyToHookSourceData.forEach(hookSourceData => { + if (hookSourceData.sourceConsumer != null) { + // Use cached source map consumer. return; } @@ -189,9 +235,13 @@ function extractAndLoadSourceMaps( } } else { for (let i = 0; i < sourceMappingURLs.length; i++) { + const {runtimeSourceURL} = hookSourceData; const sourceMappingURL = sourceMappingURLs[i]; const index = sourceMappingURL.indexOf('base64,'); if (index >= 0) { + // TODO (named hooks) deduplicate parsing in this branch (similar to fetching in the other branch) + // since there can be multiple location keys per source map. + // Web apps like Code Sandbox embed multiple inline source maps. // In this case, we need to loop through and find the right one. // We may also need to trim any part of this string that isn't based64 encoded data. @@ -211,13 +261,17 @@ function extractAndLoadSourceMaps( // Hook source might be a URL like "https://4syus.csb.app/src/App.js" // Parsed source map might be a partial path like "src/App.js" - const fileName = ((hookSourceData.hookSource.fileName: any): string); const match = parsed.sources.find( source => - source === 'Inline Babel script' || fileName.includes(source), + source === 'Inline Babel script' || + runtimeSourceURL.endsWith(source), ); if (match) { - hookSourceData.sourceMapContents = parsed; + setPromises.push( + new SourceMapConsumer(parsed).then(sourceConsumer => { + hookSourceData.sourceConsumer = sourceConsumer; + }), + ); break; } } else { @@ -227,7 +281,7 @@ function extractAndLoadSourceMaps( ); } - let url = sourceMappingURLs[0].split('=')[1]; + let url = sourceMappingURLs[i].split('=')[1]; if (ABSOLUTE_URL_REGEX.test(url)) { const baseURL = url.slice(0, url.lastIndexOf('/')); url = `${baseURL}/${url}`; @@ -235,19 +289,38 @@ function extractAndLoadSourceMaps( if (!isValidUrl(url)) { throw new Error(`Invalid source map URL "${url}"`); } + } else if (!url.startsWith('/')) { + // Resolve paths relative to the location of the file name + const lastSlashIdx = runtimeSourceURL.lastIndexOf('/'); + if (lastSlashIdx !== -1) { + const baseURL = runtimeSourceURL.slice( + 0, + runtimeSourceURL.lastIndexOf('/'), + ); + url = `${baseURL}/${url}`; + } } hookSourceData.sourceMapURL = url; - if (__DEBUG__) { - console.log( - 'extractAndLoadSourceMaps() External source map "' + url + '"', + const fetchPromise = + fetchPromises.get(url) || + fetchFile(url).then( + sourceMapContents => + new SourceMapConsumer(JSON.parse(sourceMapContents)), ); + if (__DEBUG__) { + if (!fetchPromises.has(url)) { + console.log( + `extractAndLoadSourceMaps() External source map "${url}"`, + ); + } } - promises.push( - fetchFile(url).then(sourceMapContents => { - hookSourceData.sourceMapContents = JSON.parse(sourceMapContents); + fetchPromises.set(url, fetchPromise); + setPromises.push( + fetchPromise.then(sourceConsumer => { + hookSourceData.sourceConsumer = sourceConsumer; }), ); break; @@ -255,7 +328,7 @@ function extractAndLoadSourceMaps( } } }); - return Promise.all(promises); + return Promise.all(setPromises); } function fetchFile(url: string): Promise { @@ -268,9 +341,15 @@ function fetchFile(url: string): Promise { resolve(text); }) .catch(error => { + if (__DEBUG__) { + console.log(`fetchFile() Could not read text for url "${url}"`); + } reject(null); }); } else { + if (__DEBUG__) { + console.log(`fetchFile() Got bad response for url "${url}"`); + } reject(null); } }); @@ -279,11 +358,13 @@ function fetchFile(url: string): Promise { function findHookNames( hooksList: Array, - fileNameToHookSourceData: Map, + locationKeyToHookSourceData: Map, ): HookNames { const map: HookNames = new Map(); hooksList.map(hook => { + // TODO (named hooks) We should probably filter before this point, + // otherwise we are loading and parsing source maps and ASTs for nothing. if (isNonDeclarativePrimitiveHook(hook)) { if (__DEBUG__) { console.log('findHookNames() Non declarative primitive hook'); @@ -300,7 +381,8 @@ function findHookNames( return null; // Should not be reachable. } - const hookSourceData = fileNameToHookSourceData.get(fileName); + const locationKey = getLocationKey(hookSource); + const hookSourceData = locationKeyToHookSourceData.get(locationKey); if (!hookSourceData) { return null; // Should not be reachable. } @@ -321,7 +403,10 @@ function findHookNames( } else { originalSourceLineNumber = sourceConsumer.originalPositionFor({ line: lineNumber, - column: columnNumber, + + // Column numbers are representated differently between tools/engines. + // For more info see https://github.com/facebook/react/issues/21792#issuecomment-873171991 + column: columnNumber - 1, }).line; } @@ -346,7 +431,7 @@ function findHookNames( ); if (__DEBUG__) { - console.log('findHookNames() Found name "' + (name || '-') + '"'); + console.log(`findHookNames() Found name "${name || '-'}"`); } map.set(hook, name); @@ -366,103 +451,133 @@ function isValidUrl(possibleURL: string): boolean { } function loadSourceFiles( - fileNameToHookSourceData: Map, + locationKeyToHookSourceData: Map, ): Promise<*> { - const promises = []; - fileNameToHookSourceData.forEach((hookSourceData, fileName) => { - promises.push( - fetchFile(fileName).then(runtimeSourceCode => { + // Deduplicate fetches, since there can be multiple location keys per file. + const fetchPromises = new Map(); + + const setPromises = []; + locationKeyToHookSourceData.forEach(hookSourceData => { + const {runtimeSourceURL} = hookSourceData; + const fetchPromise = + fetchPromises.get(runtimeSourceURL) || + fetchFile(runtimeSourceURL).then(runtimeSourceCode => { if (runtimeSourceCode.length > MAX_SOURCE_LENGTH) { throw Error('Source code too large to parse'); } - if (__DEBUG__) { console.groupCollapsed( - 'loadSourceFiles() fileName "' + fileName + '"', + `loadSourceFiles() runtimeSourceURL "${runtimeSourceURL}"`, ); console.log(runtimeSourceCode); console.groupEnd(); } - + return runtimeSourceCode; + }); + fetchPromises.set(runtimeSourceURL, fetchPromise); + setPromises.push( + fetchPromise.then(runtimeSourceCode => { hookSourceData.runtimeSourceCode = runtimeSourceCode; }), ); }); - return Promise.all(promises); + return Promise.all(setPromises); } async function parseSourceAST( - fileNameToHookSourceData: Map, + locationKeyToHookSourceData: Map, ): Promise<*> { - // SourceMapConsumer.initialize() does nothing when running in Node (aka Jest) - // because the wasm file is automatically read from the file system - // so we can avoid triggering a warning message about this. - if (!__TEST__) { - if (__DEBUG__) { - console.log('parseSourceAST() Initializing source-map library ...'); - } - - // $FlowFixMe - const wasmMappingsURL = chrome.extension.getURL('mappings.wasm'); - - SourceMapConsumer.initialize({'lib/mappings.wasm': wasmMappingsURL}); - } - - const promises = []; - fileNameToHookSourceData.forEach(hookSourceData => { + locationKeyToHookSourceData.forEach(hookSourceData => { if (hookSourceData.originalSourceAST !== null) { // Use cached metadata. return; } - const {runtimeSourceCode, sourceMapContents} = hookSourceData; - if (sourceMapContents !== null) { + const {sourceConsumer} = hookSourceData; + const runtimeSourceCode = ((hookSourceData.runtimeSourceCode: any): string); + let originalSourceURL, originalSourceCode; + if (sourceConsumer !== null) { // Parse and extract the AST from the source map. - promises.push( - SourceMapConsumer.with( - sourceMapContents, - null, - (sourceConsumer: SourceConsumer) => { - hookSourceData.sourceConsumer = sourceConsumer; - - // Now that the source map has been loaded, - // extract the original source for later. - const source = sourceMapContents.sources[0]; - const originalSourceCode = sourceConsumer.sourceContentFor( - source, - true, - ); + const {lineNumber, columnNumber} = hookSourceData.hookSource; + if (lineNumber == null || columnNumber == null) { + throw Error('Hook source code location not found.'); + } + // Now that the source map has been loaded, + // extract the original source for later. + const {source} = sourceConsumer.originalPositionFor({ + line: lineNumber, - if (__DEBUG__) { - console.groupCollapsed( - 'parseSourceAST() Extracted source code from source map', - ); - console.log(originalSourceCode); - console.groupEnd(); - } + // Column numbers are representated differently between tools/engines. + // For more info see https://github.com/facebook/react/issues/21792#issuecomment-873171991 + column: columnNumber - 1, + }); + + if (source == null) { + // TODO (named hooks) maybe fall back to the runtime source instead of throwing? + throw new Error( + 'Could not map hook runtime location to original source location', + ); + } - hookSourceData.originalSourceCode = originalSourceCode; + // TODO (named hooks) maybe canonicalize this URL somehow? + // It can be relative if the source map specifies it that way, + // but we use it as a cache key across different source maps and there can be collisions. + originalSourceURL = (source: string); + originalSourceCode = (sourceConsumer.sourceContentFor( + source, + true, + ): string); - // TODO Parsing should ideally be done off of the main thread. - hookSourceData.originalSourceAST = parse(originalSourceCode, { - sourceType: 'unambiguous', - plugins: ['jsx', 'typescript'], - }); - }, - ), - ); + if (__DEBUG__) { + console.groupCollapsed( + 'parseSourceAST() Extracted source code from source map', + ); + console.log(originalSourceCode); + console.groupEnd(); + } } else { // There's no source map to parse here so we can just parse the original source itself. - hookSourceData.originalSourceCode = runtimeSourceCode; + originalSourceCode = runtimeSourceCode; + // TODO (named hooks) This mixes runtimeSourceURLs with source mapped URLs in the same cache key space. + // Namespace them? + originalSourceURL = hookSourceData.runtimeSourceURL; + } + + hookSourceData.originalSourceCode = originalSourceCode; + hookSourceData.originalSourceURL = originalSourceURL; - // TODO Parsing should ideally be done off of the main thread. - hookSourceData.originalSourceAST = parse(runtimeSourceCode, { + // The cache also serves to deduplicate parsing by URL in our loop over + // location keys. This may need to change if we switch to async parsing. + const sourceMetadata = originalURLToMetadataCache.get(originalSourceURL); + if (sourceMetadata != null) { + if (__DEBUG__) { + console.groupCollapsed( + `parseSourceAST() Found cached source metadata for "${originalSourceURL}"`, + ); + console.log(sourceMetadata); + console.groupEnd(); + } + hookSourceData.originalSourceAST = sourceMetadata.originalSourceAST; + hookSourceData.originalSourceCode = sourceMetadata.originalSourceCode; + } else { + // TODO (named hooks) Parsing should ideally be done off of the main thread. + const originalSourceAST = parse(originalSourceCode, { sourceType: 'unambiguous', plugins: ['jsx', 'typescript'], }); + hookSourceData.originalSourceAST = originalSourceAST; + if (__DEBUG__) { + console.log( + `parseSourceAST() Caching source metadata for "${originalSourceURL}"`, + ); + } + originalURLToMetadataCache.set(originalSourceURL, { + originalSourceAST, + originalSourceCode, + }); } }); - return Promise.all(promises); + return Promise.resolve(); } function flattenHooksList( @@ -479,23 +594,21 @@ function flattenHooksList( } function updateLruCache( - fileNameToHookSourceData: Map, + locationKeyToHookSourceData: Map, ): Promise<*> { - fileNameToHookSourceData.forEach( - ({originalSourceAST, originalSourceCode, sourceConsumer}, fileName) => { - // Only set once to avoid triggering eviction/cleanup code. - if (!fileNameToMetadataCache.has(fileName)) { - if (__DEBUG__) { - console.log('updateLruCache() Caching metada for "' + fileName + '"'); - } - - fileNameToMetadataCache.set(fileName, { - originalSourceAST, - originalSourceCode: ((originalSourceCode: any): string), - sourceConsumer, - }); + locationKeyToHookSourceData.forEach(({sourceConsumer, runtimeSourceURL}) => { + // Only set once to avoid triggering eviction/cleanup code. + if (!runtimeURLToMetadataCache.has(runtimeSourceURL)) { + if (__DEBUG__) { + console.log( + `updateLruCache() Caching runtime metadata for "${runtimeSourceURL}"`, + ); } - }, - ); + + runtimeURLToMetadataCache.set(runtimeSourceURL, { + sourceConsumer, + }); + } + }); return Promise.resolve(); } diff --git a/packages/react-devtools-shared/src/hookNamesCache.js b/packages/react-devtools-shared/src/hookNamesCache.js index 6b3ca25af28..1b979c8e191 100644 --- a/packages/react-devtools-shared/src/hookNamesCache.js +++ b/packages/react-devtools-shared/src/hookNamesCache.js @@ -9,6 +9,7 @@ import {unstable_getCacheForType as getCacheForType} from 'react'; import {enableHookNameParsing} from 'react-devtools-feature-flags'; +import {__DEBUG__} from 'react-devtools-shared/src/constants'; import type {HooksTree} from 'react-debug-tools/src/ReactDebugHooks'; import type {Thenable, Wakeable} from 'shared/ReactTypes'; @@ -108,6 +109,10 @@ export function loadHookNames( return; } + if (__DEBUG__) { + console.log('[hookNamesCache] onSuccess() hookNames:', hookNames); + } + if (hookNames) { const resolvedRecord = ((newRecord: any): ResolvedRecord); resolvedRecord.status = Resolved; @@ -121,6 +126,10 @@ export function loadHookNames( wake(); }, function onError(error) { + if (__DEBUG__) { + console.log('[hookNamesCache] onError() error:', error); + } + if (didTimeout) { return; } @@ -134,7 +143,11 @@ export function loadHookNames( ); // Eventually timeout and stop trying to load names. - let timeoutID = setTimeout(() => { + let timeoutID = setTimeout(function onTimeout() { + if (__DEBUG__) { + console.log('[hookNamesCache] onTimeout()'); + } + timeoutID = null; didTimeout = true;