Implements issue 3mhyfp5om4p26 — Script element loading and execution (defer, async).
Changes #
New: script_loader module (crates/browser/src/script_loader.rs) #
- Walks the DOM in document order for
<script>elements after HTML parsing - Executes inline scripts and fetches external scripts via
ResourceLoader - All scripts share a single JS VM with full DOM access (
attach_document) - Respects
typeattribute: only executestext/javascriptor no-type scripts deferexternal scripts are queued and executed after all synchronous scriptsasyncscripts execute immediately (no ordering guarantee)- Script errors are caught and logged without crashing the page
- After execution, document is detached from VM and returned for rendering
JS compiler: top-level var stores to global scope #
- Top-level
vardeclarations now also emitStoreGlobal, matching function declaration behavior. This ensures variables persist across separateexecute()calls when multiple scripts share a VM.
VM: detach_document() method #
- Reclaims the
Documentfrom the DOM bridge after script execution - Enables the pattern: parse → attach → execute scripts → detach → render
Resource loader: Script variant #
- Added
Resource::Scriptfor JavaScript MIME types - Updated MIME classifier with
text/javascript,application/javascript - Exhaustive match updates in
css_loaderandimg_loader
Integration in main.rs #
load_page()now callsexecute_page_scripts()between HTML parsing and CSS/image collection, so scripts can modify the DOM before styling.
Tests #
9 new tests covering:
- Inline script execution with DOM modification
- Multiple scripts sharing global scope
- Unknown
typeattribute prevents execution type="text/javascript"executes correctly- Script errors don't prevent subsequent scripts
- Empty scripts don't crash
deferinline scripts (treated as sync per spec)createElement/appendChildfrom scripts- Pages with no scripts pass through unchanged