Table of Contents
- HTML Parser
Welcome to the second Shadow devlog! If you don’t know it, Shadow is my novel browser engine made almost entirely in JS. Shadow is 2 weeks old as of this post! 🎂
(left/top: now, right/bottom: last post)
It was completely busted before, but now is quite good! The header looks broken as we do not have flex support yet.
The results did not display before as it used unsupported DOM APIs, but we now implement them so it shows fine now. Also looks a bit better due to some layout fixes.
Before it was completely broken, but now it no longer crashes! It doesn’t look great but progress is progress :)
I did a lot of work on performance and debug tools to help investigate it. I mostly cared about load time performance but did a bit of work on rendering too.
New Debug Overlay
Shadow has a new debug overlay, showing frame time and delta time (accessed via Shift+Z).
Page Load Profiler
Additionally, we now profile page loads to see what takes up the time.
~3x Faster Page Load
~2x Faster Rendering
Rendering the page is also ~2x faster than before, thanks to adding offscreen culling (not rendering elements outside of the viewport).
Shadow is now beginning to implement pseudo-classes. We currently implement
Shadow now supports the
var() CSS function, including a default value (
The CSS parser now also supports psuedo-classes, and can now parse at-rules so no longer crashes when encountering them (although they are just ignored in layout for now). It also now bails instead of crashing the entire tab when it errors.
~8x Faster Dead Text Node Removal
Removing dead text nodes is a pass layout does after assembling the layout tree to simplify it for us later. It removes unneeded text nodes (empty, or pure whitespace which can be appended to others).
I rewrote it to be ~8x faster which noticably helps page load times with big pages.
- Fixed some CSS selector matching bugs
- Fixed % values for position absolute
- Rewrote computing element’s height
~5x Faster Worker Execution Loop
The worker execution loop (how the worker loops into getting JS to eval) is now async, so it no longer sits there constantly using CPU when not executing JS. This also makes execution ~5x faster due to not having to wait a loop cycle.
createTextNode are now implemented, also some of
Attributes Without Value
The HTML parser can now parse attributes without a value, eg
Autofix Mismatching Closing Tags
The HTML parser now also tries to automatically fix mismatching closing tags. For example:
<main> <ul> <li>item </main> <article> </ul> </li> </article>
Gets transformed into:
<main> <ul> <li>item</li> </ul> </main> <article> </article>
Thanks for reading! Hope you found it interesting. Tune in next week (🤞) for this week’s progress, or watch my Twitter for “live” updates.