Can't pretty-print inline scripts
Categories
(DevTools :: Debugger, enhancement, P2)
Tracking
(firefox113 fixed)
Tracking | Status | |
---|---|---|
firefox113 | --- | fixed |
People
(Reporter: hsteen, Assigned: nchevobbe)
References
(Blocks 3 open bugs, Regressed 1 open bug, )
Details
(Keywords: DevAdvocacy, Whiteboard: [polish-backlog][DevRel:P1], dt-webcompat, [devtools:relnote])
Attachments
(2 files, 1 obsolete file)
Reporter | ||
Comment 1•11 years ago
|
||
Comment 2•11 years ago
|
||
Comment 3•11 years ago
|
||
Comment 4•11 years ago
|
||
Comment 5•11 years ago
|
||
Comment 6•11 years ago
|
||
Comment 7•11 years ago
|
||
Comment 8•11 years ago
|
||
Comment 9•11 years ago
|
||
Comment 10•11 years ago
|
||
Comment 11•11 years ago
|
||
Comment 12•11 years ago
|
||
Comment 13•11 years ago
|
||
Updated•10 years ago
|
Comment 14•10 years ago
|
||
![]() |
||
Comment 15•10 years ago
|
||
Updated•9 years ago
|
Updated•9 years ago
|
Comment 16•9 years ago
|
||
Reporter | ||
Comment 17•9 years ago
|
||
Reporter | ||
Comment 18•9 years ago
|
||
Updated•9 years ago
|
Comment 19•7 years ago
|
||
Updated•7 years ago
|
Updated•6 years ago
|
Comment 20•5 years ago
|
||
… and back from GH to bugzilla, pardon the noise.
Updated•5 years ago
|
Comment 24•4 years ago
|
||
The test case from comment #0 is also online here
http://janodvarko.cz/tests/bugzilla/1010150/
The Debugger currently doesn't show the Prettify button in this case at ll.
Honza
Assignee | ||
Updated•3 years ago
|
Comment 25•3 years ago
|
||
Note that, as part of going through bug 1569859, I'm seeing various issues around inline scripts.
So:
- I may fix issues which are blockers to implement this
- I will certainly grow knowledges around inline scripts, which are having some convoluted treatment by the thread actor.
Comment 26•3 years ago
|
||
Here is some early analysis to understand the challenge here.
How pretty print is enabled?
The pretty print button is being disabled for inline script from here:
https://searchfox.org/mozilla-central/rev/016925857e2f81a9425de9e03021dcf4251cafcc/devtools/client/debugger/src/reducers/sources.js#843-859
const sourceContent =
source.content && isFulfilled(source.content) ? source.content.value : null;
if (!sourceContent || !isJavaScript(source, sourceContent)) {
return false;
}
isJavaScript(source, sourceContent)
returns false, because the source's content type is "text/html"
.
This is checked over here:
https://searchfox.org/mozilla-central/rev/016925857e2f81a9425de9e03021dcf4251cafcc/devtools/client/debugger/src/utils/source.js#79
If we relax this first check, pretty printing is also blocked just before trying to pretty print over here:
https://searchfox.org/mozilla-central/rev/016925857e2f81a9425de9e03021dcf4251cafcc/devtools/client/debugger/src/actions/sources/prettyPrint.js#42-61
if (!isJavaScript(generatedSource, content) || content.type !== "text") {
throw new Error("Can't prettify non-javascript files.");
}
const url = getPrettyOriginalSourceURL(generatedSource);
const { code, mappings } = await prettyPrint({
text: content.value,
url,
});
If we also relax this check, prettyPrint()
method throws as it really only accepts Javascript code and isn't designed to process HTML with inline <script> tags.
What happens in the frontend regarding inline scripts
With this simple example, loading 3 trivial inline <script>'s in the base HTML file:
http://techno-barje.fr/fission/inlines/
We end up with one redux source (i.e. devtools/client/debugger/src/reducers/sources.js):
{
"id": "source-http://techno-barje.fr/fission/inlines/",
"url": "http://techno-barje.fr/fission/inlines/",
"relativeUrl": "/fission/inlines/",
"isPrettyPrinted": false,
"extensionName": null,
"isBlackBoxed": false,
"isWasm": false,
"isExtension": false,
"isOriginal": false,
"content": {
"state": "fulfilled",
"value": {
"type": "text",
"value": "\nInline scripts\n\n<script>\nconsole.log(\"first inline\");\n</script>\n\n<script>\nconsole.log(\"second inline\");\n</script>\n\n<script>\nconsole.log(\"third inline\");\n</script>\n",
"contentType": "text/html"
}
}
}
But three distinct redux source actors (i.e. devtools/client/debugger/src/reducers/source-actors.js)
[
{
"id": "server0.conn1.windowGlobal6442450946/source22",
"actor": "server0.conn1.windowGlobal6442450946/source22",
"thread": "server0.conn1.windowGlobal6442450946/thread1",
"source": "source-http://techno-barje.fr/fission/inlines/",
"isBlackBoxed": false,
"sourceMapBaseURL": "http://techno-barje.fr/fission/inlines/",
"sourceMapURL": null,
"url": "http://techno-barje.fr/fission/inlines/",
"introductionType": "scriptElement"
},
{
"id": "server0.conn1.windowGlobal6442450946/source23",
"actor": "server0.conn1.windowGlobal6442450946/source23",
"thread": "server0.conn1.windowGlobal6442450946/thread1",
"source": "source-http://techno-barje.fr/fission/inlines/",
"isBlackBoxed": false,
"sourceMapBaseURL": "http://techno-barje.fr/fission/inlines/",
"sourceMapURL": null,
"url": "http://techno-barje.fr/fission/inlines/",
"introductionType": "scriptElement"
},
{
"id": "server0.conn1.windowGlobal6442450946/source24",
"actor": "server0.conn1.windowGlobal6442450946/source24",
"thread": "server0.conn1.windowGlobal6442450946/thread1",
"source": "source-http://techno-barje.fr/fission/inlines/",
"isBlackBoxed": false,
"sourceMapBaseURL": "http://techno-barje.fr/fission/inlines/",
"sourceMapURL": null,
"url": "http://techno-barje.fr/fission/inlines/",
"introductionType": "scriptElement"
}
]
This is where it starts being complex. How do we fetch the source content?
From the server we can only fetch javascript source content via SourceActors.
Do we fetch each individual inline script and somehow merge them?
No.
source.content.value
is actually arbitrarily fetched from the first source-actor able to respond:
https://searchfox.org/mozilla-central/rev/633345116df55e2d37be9be6555aa739656c5a7d/devtools/client/debugger/src/actions/sources/loadSourceText.js#61-87
// We only need the source text from one actor, but messages sent to retrieve
// the source might fail if the actor has or is about to shut down. Keep
// trying with different actors until one request succeeds.
let response;
const handledActors = new Set();
while (true) {
const actors = getSourceActorsForSource(state, source.id);
const actor = actors.find(({ actor: a }) => !handledActors.has(a));
handledActors.add(actor.actor);
try {
response = await client.sourceContents(actor);
break;
} catch (e) {
console.warn(`sourceContents failed: ${e}`);
}
}
return {
text: response.source,
contentType: response.contentType || "text/javascript",
};
(Note that this code looks uterly complex for no reason. getSourceActorsForSource
should hopefully be called only once... unless we workaround some weird race condition that should be fixed by some other mean)
From the server perspective, we don't return spidermonkey's Source's text
attribute, which is restricted to the Javascript code of only one given inline <script> tag.
Instead we return the full HTML page content. We load Spidermonkey's Source's url
, which is the html page:
https://searchfox.org/mozilla-central/rev/633345116df55e2d37be9be6555aa739656c5a7d/devtools/server/actors/source.js#211-227
if (this._source.text !== "[no source]" && !this._isInlineSource) {
return {
content: this.actualText(),
contentType: "text/javascript",
};
}
return this.sourcesManager.urlContents(
this.url,
/* partial */ false,
/* canUseCache */ this._isInlineSource
);
I think this is where the confusion starts as we still interact with each individual source actor.
Review of all the frontend code interacting with many source actors
-
exceptions:
https://searchfox.org/mozilla-central/rev/633345116df55e2d37be9be6555aa739656c5a7d/devtools/client/debugger/src/reducers/exceptions.js#55-78
But at the end, I'm not sure we care about which particular inline script the exception relates to.
We may simplify that by matching per URL... -
blackbox:
https://searchfox.org/mozilla-central/rev/633345116df55e2d37be9be6555aa739656c5a7d/devtools/client/debugger/src/actions/sources/blackbox.js#17-19
But this doesn't look relevant asSourceActor.blackbox
method ends up calling the shared SourcesManager:
https://searchfox.org/mozilla-central/source/devtools/server/actors/source.js#610-611
So... until the SourceActor's URL are differents or the SourceActors run in distinct threads, we should be able to call it only once, on the ThreadActor... as that's not per SourceId/SourceActor, but per URL!
(Also, we may not use the returned value of this RDP method...) -
pretty print
https://searchfox.org/mozilla-central/rev/633345116df55e2d37be9be6555aa739656c5a7d/devtools/client/debugger/src/actions/sources/loadSourceText.js#41-45
https://searchfox.org/mozilla-central/rev/633345116df55e2d37be9be6555aa739656c5a7d/devtools/client/debugger/src/actions/sources/prettyPrint.js#53-57
The source map generated by pretty fast is being "applied" to all the source actors.
For now, I don't follow what it means when there is more than one actor. -
breakable lines
https://searchfox.org/mozilla-central/rev/633345116df55e2d37be9be6555aa739656c5a7d/devtools/client/debugger/src/actions/sources/breakableLines.js#44-50
https://searchfox.org/mozilla-central/rev/633345116df55e2d37be9be6555aa739656c5a7d/devtools/server/actors/source.js#261-262
This is where we start the scratch the full complexity of inline script.
There is a quite convoluted logic on the server, in SourceActor, dedicated to inline scripts.
This is there to understand where the related inline <script> tag is in the html page.
This is what_adjustInlineScriptLocation
is about:
https://searchfox.org/mozilla-central/rev/633345116df55e2d37be9be6555aa739656c5a7d/devtools/server/actors/source.js#340-359
I will ignore the underlying issues of this particular method (which is async and brittle).
We then apply some shift between what Spidermonkey'sScript.getPossibleBreakpoints()
returns and what we report back to the frontend:
https://searchfox.org/mozilla-central/rev/633345116df55e2d37be9be6555aa739656c5a7d/devtools/server/actors/source.js#544-552
Note that this is also used when setting breakpoints:
https://searchfox.org/mozilla-central/rev/633345116df55e2d37be9be6555aa739656c5a7d/devtools/server/actors/source.js#708-715 -
make breakpoint
https://searchfox.org/mozilla-central/rev/633345116df55e2d37be9be6555aa739656c5a7d/devtools/client/debugger/src/utils/breakpoint/index.js#45-48
This code makes no sense to me.
Could we simply dobreakpointLocation.sourceId = source.id
?
Updated•2 years ago
|
Assignee | ||
Updated•2 years ago
|
Assignee | ||
Updated•2 years ago
|
Assignee | ||
Comment 27•2 years ago
|
||
This will help us getting the actual text of an inline script in DevTools
Depends on D170581
Assignee | ||
Comment 28•2 years ago
|
||
Depends on D170750
Updated•2 years ago
|
Updated•2 years ago
|
Comment 29•2 years ago
|
||
Comment on attachment 9319450 [details]
Bug 1010150 - [devtools] Add Debugger.Source.startColumn. r=jandem.
Revision D170750 was moved to bug 1819290. Setting attachment 9319450 [details] to obsolete.
Assignee | ||
Comment 30•2 years ago
|
||
Note that the event listener popup only reference the formatted file with Bug 1557196 applied
Comment 31•2 years ago
|
||
Comment 32•2 years ago
|
||
bugherder |
Assignee | ||
Comment 34•2 years ago
|
||
(In reply to Ryan VanderMeulen [:RyanVM] from comment #33)
Do you want to add this to the Fx113 relnotes?
Not sure, for now we only pretty print the content of inline script in the HTML, and not the HTML itself, which people might think is a bug. I'd rather make an announcement when/if we pretty print the html as well
Updated•2 years ago
|
Description
•