EventSource allows opening a persistent HTTP connection to a server over
which events are continuously streamed.
Unfortunately, our test infrastructure does not allow for automating any
tests of this feature yet. It only works with HTTP connections.
Supporting unbuffered fetches is actually part of the fetch spec in its
HTTP-network-fetch algorithm. We had previously implemented this method
in a very ad-hoc manner as a simple wrapper around ResourceLoader. This
is still the case, but we now implement a good amount of these steps
according to spec, using ResourceLoader's unbuffered API. The response
data is forwarded through to the fetch response using streams.
This will eventually let us remove the use of ResourceLoader's buffered
API, as all responses should just be streamed this way. The streams spec
then supplies ways to wait for completion, thus allowing fully buffered
responses. However, we have more work to do to make the other parts of
our fetch implementation (namely, Body::fully_read) use streams before
we can do this.
Download files to a temporary location, then only move the downloaded
file to the real location once the download is complete. This prevents
CMake from being confused about partially-downloaded files, e.g. if
someone presses ctrl+c in the middle of a download.
Note the GN build already behaves this way.
The logic in this script was *intended* to use the system's default
compiler if it was sufficiently new, and only start searching for the
latest installed if the default was not suitable.
However, the `cxx` program does not exist on Unixes, so the version
check always failed. We should be using the standard `c++` program name
instead.
After this change, the `CC` and `CXX` environment variables will have to
be used if someone wants to force a newer compiler version.
Now that the lambda capture plugin isn't full of false-positives, we can
make the jump and start halting builds for these errors. It also allows
these plugins to be useful in CI.
Instead of being opt-out with NOESCAPE, it is now opt-in with ESCAPING.
Opt-out is ideal, but unfortunately this was extremely noisy when
compiling the entire codebase. Escaping functions are rarer than non-
escaping ones, so let's just go with that for now.
This also allows us to gradually add heuristics for detecting missing
ESCAPING annotations and emitting them as errors. It also nicely matches
the spelling that Swift uses (@escaping), which is where this idea
originally came from.
No behavior change. No measurable performance different either.
(I tried `hyperfine 'Build/lagom/bin/image --no-output foo.webp'`
for a few input images before and after this change, and I didn't
see a difference. I also tried if moving both
Gfx::CanonicalCode::read_symbol() and
Compress::CanonicalCode::read_symbol() inline, and that didn't
help either.)
This allows readonly attributes and functions to have a 'FIXME' extended
attribute added to the IDL definition to stub out the function. This
makes debugging web compatibility issues on live sites much easier as a
FIXME message is logged whenever one of these functions or attributes
are called.
Support still needs to be extended to non-readonly attributes (and some
other special cases), but this should allow us to set a big percentage
of the commented out attributes/functions in IDL files to instead use
this extended attribute.
* Matches how the loader is organized
* `compress_VP8L_image_data()` will grow longer when we add actual
compression
* Maybe someone wants to write a lossy compressor one day
No behavior change.
The new baked image is a Prekernel and a Kernel baked together now, so
essentially we no longer need to pass the Prekernel as -kernel and the
actual kernel image as -initrd to QEMU, leaving the option to pass an
actual initrd or initramfs module later on with multiboot.
Nobody uses this functionality. I used this code on my old 2007 ICH7
test machine about a year ago, but bare metal is a small aspect of the
project, so it's safe to assume that nobody really tests this piece of
code.
Therefore, let's drop this for good and focus on more modern hardware.
Now both /bin/zcat and /bin/gunzip are symlinks to /bin/gzip, and we
essentially running it in decompression mode through these symlinks.
This ensures we don't maintain 2 versions of code to decompress Gzipped
data anymore, and handle the use case of gzipped-streaming input only
once in the codebase.
This is a more general and robust replacement of the LibJSGCVerifier.
We want to add more generic static analysis, and this new plugin will
be built in a way that integrates into the rest of the system.
🤽 - U+1F93D PERSON PLAYING WATER POLO
🤽♂️ - U+1F93D U+200D U+2642 MAN PLAYING WATER POLO
🤽♀️ - U+1F93D U+200D U+2640 WOMAN PLAYING WATER POLO
🦨 - U+1F9A8 SKUNK
The high-level design is that we have a static method on WebPWriter that
returns an AnimationWriter object. AnimationWriter has a virtual method
for writing individual frames. This allows streaming animations to disk,
without having to buffer up the entire animation in memory first.
The semantics of this function, add_frame(), are that data is flushed
to disk every time the function is called, so that no explicit `close()`
method is needed.
For some formats that store animation length at the start of the file,
including WebP, this means that this needs to write to a SeekableStream,
so that add_frame() can seek to the start and update the size when a
frame is written.
This design should work for GIF and APNG writing as well. We can move
AnimationWriter to a new header if we add writers for these.
Currently, `animation` can read any animated image format we can read
(apng, gif, webp) and convert it to an animated webp file.
The written animated webp file is not compressed whatsoever, so this
creates large output files at the moment.
Xcode clang doesn't understand the -std=c++23 spelling yet, and this
is what CMake's `set(CMAKE_CXX_STANDARD 23)` translates to too.
Unbreaks building with Xcode clang on macOS.
An AudioNode is the fundamental building block used in 'Audio
Contexts'. In our immediate case, the audio node we are working towards
implementing is an oscillating source node.
Previously the GML compiler did not support object properties such as
`content_widget: @GUI::Widget{}` for GUI::ScrollableContainerWidget;
this commit adds support for such properties by simply calling
`set_<key>(<TProperty>&)` on the object.
This commit also removes the previous hack where
ScrollableContainerWidget was special-cased to have its singular child
used as the content widget; the only GML file using this behaviour was
also changed to be in line with 'proper' GML as handled by the GML
Playground.
This makes it possible to use externally defined toplevel widgets that
have no C++ header defining them.
Note that this only allows widget-native properties on the object, as
the actual original definition is not available.
We already have required this version for quite a while for Lagom,
Ladybird and Serenity. Now that we require it in all of our CMakeLists,
let's scrub for better ways of writing things.
This allows main UI processes created while there is a currently
running one to request a new tab or a new window with the initial urls
provided on the command line. This matches (almost) the behavior of
Chromium and Firefox.
Add a new IPC protocol between two UI processes. The main UI process
will create an IPC server socket, while secondary UI processes will
connect to that socket and send over the URLs and action it wants the
main process to take.
This was resulting in a whole lot of rebuilding whenever a new IDL
interface was added.
Instead, just directly include the prototype in every C++ file which
needs it. While we only really need a forward declaration in each cpp
file; including the full prototype header (which itself only includes
LibJS/Object.h, which is already transitively brought in by
PlatformObject) - it seems like a small price to pay compared to what
feels like a full rebuild of LibWeb whenever a new IDL file is added.
Given all of these includes are only needed for the ::initialize
method, there is probably a smart way of avoiding this problem
altogether. I've considered both using some macro trickery or generating
these functions somehow instead.
The prototype header generation was getting a bit long.
This is also a step towards generating code for IDL files only
containing an enum definition without any interface. In that case we
can't put the enum definitions alongside the prototype - there is no
prototype to speak of.
We should never hit this case - so don't generate code for it, and
instead put in a VERIFY_NOT_REACHED.
Also improve the formatting of the generated code to closer match the
serenity code style.
Instead of a cryptic error that occurs due to an interface with no name,
fail early on by explicitly checking that an interface was parsed with a
name.
This change moves WebAssembly related data that was previously globally
accessible into the `WebAssemblyCache` object and creates one of these
per global object. This ensures that WebAssembly data cannot be
accessed across realms.
The following command was used to clang-format these files:
clang-format-18 -i $(find . \
-not \( -path "./\.*" -prune \) \
-not \( -path "./Base/*" -prune \) \
-not \( -path "./Build/*" -prune \) \
-not \( -path "./Toolchain/*" -prune \) \
-not \( -path "./Ports/*" -prune \) \
-type f -name "*.cpp" -o -name "*.mm" -o -name "*.h")
There are a couple of weird cases where clang-format now thinks that a
pointer access in an initializer list, e.g. `m_member(ptr->foo)`, is a
lambda return statement, and it puts spaces around the `->`.
Currently, if the prebuilt toolchain cache gets used, we will not try to
build the toolchain. Thus, the toolchain's ccache does not get used, and
is then pruned entirely at the end of the run.
So for now, let's just not prune the toolchain ccache. After a few years
it only reached 0.8 GB in size. And now that we are starting from empty
again, it would likely be a few more years before we reach 0.8 GB again.
If there is a cache miss while downloading the ccache from GitHub/Azure,
the .ccache directory won't exist when we try to update the modification
time of its contents. Configure the ccache size first, which will create
the .ccache directory if it doesn't exist.
Clang builds of ASAN+UBSAN on Linux take significantly less time on the
Azure CI runners. Measured times were 82 minutes for Clang 18 and
112 minutes for GCC 13, with no cache.
To keep our coverage of Ladybird builds + testing with GCC, add a
nightly job to run through the full test cycle on GCC 13.
It previously resided in LibWebView to hide the details of launching a
singleton process. That functionality now lives in LibCore. By moving
this to Ladybird, we will be able to register the process with the task
manager.
This just moves the code to launch a single process such as SQLServer to
LibCore. This will allow re-using this feature for other processes, and
will allow moving the launching of SQLServer to Ladybird.
This will be needed to collect statistics from processes that do not
have anything to do with LibWebView. The ProcessInfo structure must be
virtual to allow callers to add application-specific information.
This refactor eliminates the need for a second "fd passing socket" on
Lagom, as it uses SCM_RIGHTS in the expected fashion, to send fds along
with the data of our Unix socket message.
When launched with the new --enable-idl-tracing option, we now log
every call to web platform APIs declared via IDL, along with the
arguments passed.
This can be very helpful when trying to figure out what a site is
doing, especially if it's not doing what you'd expect.
On macOS, it's not trivial to get a Mach task port for your children.
This implementation registers the chrome process as a well-known
service with launchd based on its pid, and lets each child process
send over a reference to its mach_task_self() back to the chrome.
We'll need this Mach task port right to get process statistics.
C++ classes that inherit from JS::Cell and are leaf classes should have
their own type-specific allocator. We also do this for non-leaf classes
that are constructable from JS.
To do this, JSON messages are passed to communicate information about
each class the Clang tool comes across. This is the only message we have
to worry about for now, but in the future if we want to transmit
different kinds of information, we can make this message format more
generic.
This allows each Clang process to send JSON messages to the
orchestrating Python process, which aggregates the message and can do
something with them all at the end. This is required because we run
Clang multithreaded to speed up the tool execution.
I did try to add a second frontend tool that accepts all the files at
once, but it was _extremely_ slow, so this is the next best thing.
For example, consider the following code snippet:
Vector<Function<void()>> m_callbacks;
void add_callback(Function<void()> callback)
{
m_callbacks.append(move(callback));
}
// Somewhere else...
void do_something()
{
int a = 10;
add_callback([&a] {
dbgln("a is {}", a);
});
} // Oops, "a" is now destroyed, but the callback in m_callbacks
// has a reference to it!
We now statically detect the capture of "a" in the lambda above and flag
it as incorrect. Note that capturing the value implicitly with a capture
list of `[&]` would also be detected.
Of course, many functions that accept Function<...> don't store them
anywhere, instead immediately invoking them inside of the function. To
avoid a warning in this case, the parameter can be annotated with
NOESCAPE to indicate that capturing stack variables is fine:
void do_something_now(NOESCAPE Function<...> callback)
{
callback(...)
}
Lastly, there are situations where the callback does generally escape,
but where the caller knows that it won't escape long enough to cause any
issues. For example, consider this fake example from LibWeb:
void do_something()
{
bool is_done = false;
HTML::queue_global_task([&] {
do_some_work();
is_done = true;
});
HTML::main_thread_event_loop().spin_until([&] {
return is_done;
});
}
In this case, we know that the lambda passed to queue_global_task will
be executed before the function returns, and will not persist
afterwards. To avoid this warning, annotate the type of the capture
with IGNORE_USE_IN_ESCAPING_LAMBDA:
void do_something()
{
IGNORE_USE_IN_ESCAPING_LAMBDA bool is_done = false;
// ...
}
As defined in: https://w3c.github.io/pointerevents
With the exception of the getCoalescedEvents and getPredictedEvents
APIs.
There are still many other parts of that spec (such as the event
handlers) left to implement, but this does get us at least some of the
way.