Initialize the imported WPT server with the dynamic test HTTP port and
localhost-backed host aliases so .sub.html files can expand {{host}},
{{ports}}, and {{domains[...]}} during LibWeb text tests.
Teach the local http-test-server hook to serve non-.py resources through
the vendored wptserve FileHandler instead of SimpleHTTPRequestHandler,
so WPT file features like ?pipe=..., .sub., and WPT .headers processing
work for ordinary resources as well.
Requests ending with .py are also now handled through WPTs python
script handler.
Problem: Our WebSocket tests were connecting to an externally-hosted
echo server — so they depended on network reachability from our CI
runners. Any network hiccups between a runner and that server timed the
tests out — and that’s been a relatively-frequent source of CI flakes.
Fix: Teach our existing in-tree echo server to also speak WebSocket. It
performs the RFC 6455 handshake, and echoes every text or binary frame
back — on the same OS-assigned port already exposed to tests. Updated
our tests to connect to that local server, not the remote one.
Also, updated our WebSocket echo.html to drive the exchange from its
onopen handler — rather than waiting for a server-initiated greeting.
That’s because: A frame the server sends in the moment right after the
handshake — before the client has sent anything — is currently delivered
unreliably by our (curl-backed) WebSocket client. See issue #9776.
When an embedded document was render-blocked, the parent display list
recording skipped drawing that iframe's compositor surface. Once the
child document later unblocked, only the child surface was repainted, so
the parent could keep replaying a display list that had no surface draw
command until another invalidation, such as resize, forced a recording.
Invalidate the containing iframe when a document's render-blocking set
becomes empty so the parent display list records the child surface. Add
a deterministic reftest that gates a render-blocking stylesheet on a
test-server signal, forcing the parent to paint the blocked iframe
before unblocking it.
The test HTTP server used to append headers from .headers files after
SimpleHTTPRequestHandler had already emitted its own headers.
For headers such as Last-Modified, this produced duplicate response
headers. LibHTTP combines duplicate header values with ", ", which made
Document::lastModified unable to parse the configured Last-Modified
value and fall back to the current time.
Suppress SimpleHTTPServer headers whose names are provided by a .headers
file, while still allowing the explicit .headers values through.
This was iterating keys(), then calling get_all(key), which would
iterate the headers again. Not only that, but it would return all
headers with that key, so we would end up putting the same values
in the dict for every duplicate key. In practice, this shouldn't really
happen, but it's reasonable to avoid regardless.
This also fixes a type mismatch with the dict[str, list[str] | None]
being assigned to a dict[str, list].
Introduce IncrementalDocumentParser, which streams the response body
through a TextCodec::StreamingDecoder into the HTMLTokenizer one chunk
at a time. The tokenizer pauses when it runs out of input and resumes
once the next chunk is appended; when the body closes we close the
tokenizer's input stream so it can finish the parse.
DocumentLoading routes HTML responses through the new parser instead of
buffering the full body before handing it to HTMLParser.
When we request the HTTP cookie for a SWR request, we were providing the
cookie to the standard request corresponding to the SWR request's ID.
This had two effects:
1. The SWR request would never finish.
2. If the corresponding standard request happened to be a connect-only
request, this would result in a crash as we were expecting it to have
gone through the normal fetch process.
This was seen on some articles on news.google.com.
Imported WPT tests often load resources using canonical absolute paths,
for example:
/html/browsers/windows/resources/message-parent.html
Our usual strategy is to rewrite such URLs to relative paths during
import so they resolve from the importing test HTML file (which also
allows for loading this HTML as a file://).
That works for same-origin relative loading with the echo server, but it
breaks down when a test constructs a cross-origin URL from an absolute
path, for example:
get_host_info().REMOTE_ORIGIN + "/some/wpt/path.html"
In that case the resource still needs to be fetched at its canonical
absolute path, so rewriting it relative to the importing document is no
longer sufficient.
Update the HTTP test server so /static/ continues to serve from the
general test root, other non-echo requests are served from the imported
WPT tree, and dynamically registered echo responses live under /echo/
to avoid path conflicts.
The http-test-server.py change allows repeated fixed /echo route
registration by Text/input/navigation/iframe-referrer-policy.html.
Before this change, the second registration of the same method+path+def
returned 409, causing include.js to throw and fail the test.
Make /echo registration idempotent for identical definitions and return
success, but keep 409 for conflicting redefinitions of an existing
method+path.
It's possible for the cookie value from a Set-Cookie header to contain
invalid UTF-8. We must isomorphic decode this header.
This fixes the /cookies/domain/domain-attribute-idn-host.sub.https.html
WPT test. The test added here is a crash test rather than a text test
because we cannot access the received Set-Cookie header from JS on the
file:// test URL.
Also, allow the echo server to reflect headers by substituting it into a
provided template body, enabling them to be read programmatically as
part of a script.
If we have the response for a non-Range request in the memory cache, we
would previously use it in reply to Range requests. Similar to commit
878b00ae61f998a26aad7f50fae66cf969878ad6, we are just punting on Range
requests in the HTTP caches for now.
If the cURL request completes with anything other than CURLE_OK, we must
not keep the cache entry. For example, if the server's connection closes
while transferring data, we receive CURLE_PARTIAL_FILE. We don't want
this cache entry to be treated as valid in a subsequent request.
Add an option to http-test-server.py to return received headers as the
response body. This is useful for checking that outgoing headers are
correct, for example in cookie tests.
The `str | None` syntax is only supported in Python 3.10+ and we can
support more Python versions without compromising readability by
importing the `Optional` type.
This commit makes the following changes:
- Adds a model "Echo" for the request body
- Changes the main endpoint from /create to /echo (more REST-y)
- Sends "400: Bad Request" for invalid params or a reserved path
- Sends "409: Conflict" when trying to use an already registered path
- Prints the server port to stdout
- Removes unnecessary subcommands/options (start, stop, --background)
This allows us to simulate HTTP responses from Browser JS tests.
Instead of using hacks like data URLs to "load" external data,
we can now generate an actual HTTP response that contains
arbitrary headers, body, and has a defined response delay.