prism: Defer breaks autoload (when loading page without having resources cached)
Information:
- Prism version: 1.17.1
- Plugins: autoloader
- Environment: Browser
Description
When the page is loaded without the JS resources being cached and the scripts are marked with defer then the syntax highlighting is not applied.
Example
Without defer (workking): https://jsfiddle.net/f5vj903e/
With defer (not working): https://jsfiddle.net/f5vj903e/1/
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Comments: 29 (15 by maintainers)
Commits related to this issue
- Removed defer from prism See PrismJS/prism#2102 — committed to AuraDevelopmentTeam/AuraDevHomepage by BrainStone 5 years ago
- Make Prism load defer again Requires: - prism to be loaded last - prism autoload to be the last script Knowledge gained from PrismJS/prism#2102 — committed to AuraDevelopmentTeam/AuraDevHomepage by BrainStone 5 years ago
- Core: Fixed race condition caused by deferring the script (#2103) This fixes a race condition that can occur when deferring Prism components. For more details see #2102. — committed to PrismJS/prism by RunDevelopment 5 years ago
Alright, I think I know what causes the race condition.
Since the
readyStateof the document isinteractive, Prism Core usesrequestAnimationFrameto highlight all code blocks. The problem with this is that this means that all plugins have to loaded and executed before the next frame. This is the reason why some plugins are sometimes active and sometimes not.(You can verify that this is indeed what’s going on by setting a breakpoint in e.g
prism-linenumbers.min.jsand you’ll see that the breakpoint sometimes hits after all code blocks have been highlighted.)This is a bit of an issue because we’ll have to wait for resources that might be loaded. Unfortunately,
deferdoesn’t work on inline scripts:So, instead of using the
requestAnimationFramepath, we should use theDOMContentLoadedpath in Prism Core becausedeferred scripts are guaranteed to be executed before that event. And to figure out whether the current script is deferred or not, we needcurrentScript. (yay, full circle) I’m imagining something along the lines of the following as a fix.Have I verified that this fix works? No. Why not? Funny story. As it turns out: the moment you add an inline script everything works. No race condition, it just works. Srsly, try it. Just add
<script>/* how? */</script>anywhere in the test page. (btw<script></script>doesn’t work. Seems like someone at Mozilla wanted to optimize) How’s that as a fix? Just add<script>/**/</script>.Ok, I just verified that the fix works. I’ll make a PR.
So I created a standalone HTML page that displays the bug (not minimal, but I think other scripts help bringing the issues out). testpage.zip
It helps if you put the page on a (slow) webserver. As locally I can’t seem to reproduce any of the issues except the wrong script tag issue, but online they still all happen.