[DevTools Bug]: Hook names fail to parse if source file for Component is an html file
jstejada opened this issue · comments
When testing our fixture in Safari (./fixtures/devtools/standalone/index.html
) with the standalone build if DevTools, I noticed that we were unable to parse hook names because the source file where the components are defined isn't a JavaScript file, and instead an HTML file (as in index.html
), which contains HTML code, and some JS inside script tags, so the babel parser fails to parse the file.
Specifically:
// parseSourceAndMetadata.js
const originalSourceAST = withSyncPerfMeasurements(
'[@babel/parser] parse(originalSourceCode)',
() =>
parse(originalSourceCode, {
sourceType: 'unambiguous',
plugins: ['jsx', plugin],
}),
);
In the above code, the call to parse
fails because originalSourceCode
is actually html (with JS inside) like:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>TODO List</title>
<!-- ... -->
<body>
<div id="root"></div>
<script type="text/javascript">
const { useState } = React;
function App() {
const [count, setCount] = useState(0);
return null;
}
ReactDOM.render(React.createElement(App), document.getElementById("root"));
</script>
</body>
And parse
expects actual JS code.
DevTools should handle the case when source files aren't JS files, and still be able to extract out the hook names, or fail more gracefully. As of #22320, we log to the console a slightly better error message when this happens, as opposed to an obscure parsing error.
Repro steps
- Run standalone app
- Open fixtures file in safari: ./fixtures/devtools/standalone/index.html
- Try getting hook names, observe that parsing source files fails
I think the title of this issue might be misleading. (I might be wrong but) I don't think the cause is an inline <script type="text/javascript">
tag but rather the fact that our demo uses <script type="text/babel">
which has non-standard JS syntax (JSX) that requires a special plug-in to parse.
We could look into how much weight this additional plug-in would add to the bundle, but initially I lean towards saying that should just explicitly not support JSX syntax.
Again though, I could be wrong and maybe it really is the inline tag part.
@bvaughn so i tested this by making the index.html file only contain a regular "text/javascript"
script tag, without jsx or anything:
and our call to babel.parse()
still fails for parse the file, I presume because parse()
expects the input to be JS , but we are passing html, so it fails to parse the html outside the script tags.
not sure what the best approach would be here, maybe try to extract the JS from script tags if we detect that the source file is an html file?
The "HTML" you're referring to above is also JSX :)
React.createElement('div', {id: 'root'}; // <div id="root"
we discussed offline and there was confusion about what I was referring to in this issue. I updated the summary to try to clarify the problem.
As of #22320, we log to the console a slightly better error message when this happens, as opposed to an obscure parsing error
For added context, the error I'm seeing in the console is:
Error: Hook source code location not found.
at u (hookNamesCache.js:215)
at loadSourceAndMetadata.js:435
This happens before the parsing step. I wonder what has changed since you originally posted this?
Digging in further, that's because hookSource
is missing a file name, e.g.:
hookSource: {
columnNumber: 22,
fileName: undefined,
functionName: "ListItem",
lineNumber: 131,
}
Looking at the error-stack-parser
source, it seems like an undefined fileName
indicates a stack frame of either "eval"
or "<anonymous>"
. Sure enough, looking at the Error
stack for one of our components defined in an HTML file like this, I see e.g. " at ListItem (<anonymous>:135:22)"
.
I'm not sure if there's much we can do about this.
I'm seeing this same behavior (an undefined fileName
) when using both Chrome and Safari.