This patchset makes ProtocolServer stream the downloads to its client
(LibProtocol), and as such changes the download API; a possible
download lifecycle could be as such:
notation = client->server:'>', server->client:'<', pipe activity:'*'
```
> StartDownload(GET, url, headers, {})
< Response(0, fd 8)
* {data, 1024b}
< HeadersBecameAvailable(0, response_headers, 200)
< DownloadProgress(0, 4K, 1024)
* {data, 1024b}
* {data, 1024b}
< DownloadProgress(0, 4K, 2048)
* {data, 1024b}
< DownloadProgress(0, 4K, 1024)
< DownloadFinished(0, true, 4K)
```
Since managing the received file descriptor is a pain, LibProtocol
implements `Download::stream_into(OutputStream)`, which can be used to
stream the download into any given output stream (be it a file, or
memory, or writing stuff with a delay, etc.).
Also, as some of the users of this API require all the downloaded data
upfront, LibProtocol also implements `set_should_buffer_all_input()`,
which causes the download instance to buffer all the data until the
download is complete, and to call the `on_buffered_download_finish`
hook.
Specification: https://dom.spec.whatwg.org/#concept-event-dispatch
This also introduces shadow roots due to it being a requirement of
the event dispatcher.
However, it does not introduce the full shadow DOM, that can be
left for future work.
This changes some event dispatches which require certain attributes
to be initialised to a value.
`DOM::XMLHttpRequest` now checks if the requested URL has the same
`Origin` as the requesting `Document`. If the requested URL is in
violation of SOP the request is rejected and an "error" `DOM::Event`
is dispatched.
This will be inherited by documents and workers, to provide a common
abstraction for script execution. (We don't have workers yet, but we
might as well make this little space for them now to simplify things
down the road.)
For now, the new DOM::EventDispatcher is very simple, it just iterates
over the set of listeners on an EventTarget and invokes the callbacks
as it goes.
This simplifies EventTarget subclasses since they no longer have to
implement the callback mechanism themselves.
The fact that a `MarkedValueList` had to be created was just annoying,
so here's an alternative.
This patchset also removes some (now) unneeded MarkedValueList.h includes.
Decorated Interpreter::call() with [[nodiscard]] to provoke thinking
about the returned value at each call site. This is definitely not
perfect and we should really start thinking about slimming down the
public-facing LibJS interpreter API.
Fixes#3136.
LibWeb keeps growing and the Web namespace is filling up fast.
Let's put DOM stuff into Web::DOM, just like we already started doing
with SVG stuff in Web::SVG.
Instead of taking the JS::Heap&. This allows us to get rid of some
calls to JS::Interpreter::global_object(). We're getting closer and
closer to multiple global objects. :^)
We still have to hand-write a function to turn an Event& into a wrapper
but this is still a hue improvement. Eventually we'll find a way to
auto-generate that function as well.
We now store the response headers in a download object on the protocol
server side and pass it to the client when finishing up a download.
Response headers are passed as an IPC::Dictionary. :^)
A MarkedValueList is basically a Vector<JS::Value> that registers with
the Heap and makes sure that the stored values don't get GC'd.
Before this change, we were unsafely keeping Vector<JS::Value> in some
places, which is out-of-reach for the live reference finding logic
since Vector puts its elements on the heap by default.
We now pass all the JavaScript tests even when running with "js -g",
which does a GC on every heap allocation.
In order to complete a relative URL, we need a Document. Fix this by
giving XMLHttpRequest a pointer to its window object. Then we can go
from the window to the document, and then we're home free. :^)
This patch adds very basic XMLHttpRequest support to LibWeb. Here's an
example that currently works:
var callback = function() { alert(this.responseText); }
var xhr = new XMLHttpRequest();
xhr.addEventListener("load", callback);
xhr.open("GET", "http://serenityos.org/~kling/test/example.txt");
xhr.send();
There are many limitations and bugs, but it's pretty dang awesome that
we have XHR. :^)