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.
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.
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.
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 `->`.
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.
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.
Previously, parsing would continue if a parameter wasn't given a name
and malformed code would be generated, leading to hard to diagnose
compiler errors.