Make sure jemallocator is disabled in Release builds (we only use it in Debug
builds to collect metrics. Supposedly something changed in our 0.16 build that
causes it to be initialized even though it isn't used. Not sure, for this, I'm
just doing what Claude tell me, but disabling something in Release that I know
we aren't using sounds ok).
Builds on top of the recently added support for <link rel=preload...> and
<link rel=modulePreload...> to scan the HTML for script tags to preload. I.e.
adds script preloading without actually having any preload hits.
At least for this first pass, I opted for a simple approach which leverages
are fully buffered HTML body and html5ever's tokenizer to prescan the body and
kickoff any script fetching before starting the complete parse.
There are doubtless cases where this will either decrease performance and/or
increase memory usage. E.g. a site with no script gets its html scanned twice
and loading multiple blocking scripts in parallel obvious uses more memory
than loading them sequentially. But for most sites and I think most use-cases,
the impact should range between neutral to significantly faster loads.
This is something most browsers do.
In a custom element, when this.innerHTML = '....' is called, we need to be
careful to prevent endless recursion. The html5ever callback used to determine
the context element should not invoke the custom-element constructor, else we'll
enter an endless loop.
This also fixes an ungating problem added with the new HttpClient when a
waitForImport can block forever.
Both issues were see on a WooCommerce site - though the HttpClient is only
due to an earlier HttpClient refactor.
On for the main document parsing should a leading BOM be stripped. When setting
innerHTML, it should be preserved (and becomes a text node).
Fixes react hydration issue with theverge.com
The parsing behavior of HTML depends on what we're parsing it for. innerHTML on
a script is parsed (slightly) differently than for, say, the body. html5ever
supports this, we just have to give it the tag name (which we have access to
in the html5ever bridge already).
Also, extend the tag types that dump does NOT escape for beyond noscript/script.
Fixes warnings with some NextJS sites
Implements `url_resolve_with_encoding` and `url_resolve_without_encoding` in Rust; that way, we don't pay the cost of extra `Box`es we allocate during resolving.
This is a bit all over the place.
1 - Replace libidn2 with rust-idna. It looks like there are different idna
profiles, and rust-idna (from the servo project) implements the whatwg
one. libidn2 would be too strict in some cases and not strict enough in
others. (Gemini says I could use libidn2 for this, but what it suggested
didn't work, and I couldn't figure it out myself, and claude insisted it
_did not_ have the correct implementation for what we want).
2 - We previously only ran a URL through idna if it wasn't ascii. Turns out
we also need to run it if there's a "xn--" (aka, an IDNA ACE prefix) in
there. This helps us pass hundreds of WPT cases, and it's pretty cheap.
3 - Implement more of the Area WebAPI. Mostly copied from Anchor.
4 - Add username/password accessor to Anchor/Area
5 - window.open validates the URL (i.e. tries to resolve it and handles the
error)
6 - Invalid idna conversion maps to a TypeError
7 - Cleanup closed popups on the next tick (like destroyed pages), rather than
at an interval or on shutdown. This one seems unrelated, but some of these
tests are opening hundreds (thousands?) of popups and then closing them.
Normally, a shadow dom is attached to an element via `el.attachShadow(mode)`.
With DSD, the shadow dom is attached during parsing. Essentially, when we see:
<template shadowrootmode="open">...</template>
it has the end result of calling attachShadow on the parent element. This is
used increasingly by a number of frameworks, though normally with backwards
compatibility that fallbacks to doing it in JavaScript.
DSD happens during parsing and document.write, but not via innerHTML = ''.
However, both Element and DocumentFragment gain a `setHTMLUnsafe` which is like
innerHTML WITH DSD.
I initially thought this feature could be implement exactly like I describe:
when the parser adds a template, check for a `shadowrootmode` attribute and
call attachShadow...except..you need to call attachShadow on the parent, which
the parser hasn't popped yet, and it alters where the children are added.
Thankfully, html5ever has a boolean to enable/disable dsd..hence the html5ever
binding changes to (a) enable / disable this featuer and (b) the new callback.
Whenever we resolve a URL, say from `anchor.href`, we should consider the
document's charset when encoding the querystring. This probably isn't the
most important feature, but it makes tens of thousands of WPT cases pass, e.g
/encoding/legacy-mb-tchinese/big5/big5-encode-href-errors-han.html?3001-4000 and
/encoding/legacy-mb-japanese/euc-jp/eucjp-encode-href-errors-han.html?17001-18000
DOM elements previous called `URL.resolveURL(...)`. They now call
`self.asNode().resolveURL(...)`, where `Node#resolveURL` will provide the
document's charset.
Uses the newly added encoding_rs to implement TextDecoder for all encoding.
Claude wrote 100% of the Rust binding.
Improves various WPT tests, e.g. /encoding/api-basics.any.html.
Fixes issues reported by polyglot-scanner:
- Removed explicit `return` keywords and trailing semicolons to resolve DEAD_CODE/DEAD_BRANCH warnings.
- Replaced `epoch::advance().unwrap()` and `stats::resident::read().unwrap()` with safer alternatives (`drop` and `unwrap_or(0)`) to resolve ERROR_SWALLOW warnings.
- Replaced `let _ = Box::from_raw(...)` with `drop(Box::from_raw(...))` to correctly drop the box while fixing the ERROR_SWALLOW warning.