mirror of
https://github.com/fergalmoran/ladybird.git
synced 2026-05-02 01:12:32 +00:00
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;
// ...
}
LibJSGCVerifier
This is a simple Clang tool to validate certain behavior relating to LibJS's GC. It currently validates two things:
- For all types wrapped by
GCPtrorNonnullGCPtr, that the wrapped type inherits fromCell - For all types not wrapped by
GCPtrorNonnullGCPtr, that the wrapped type does not inherit fromCell(otherwise it should be wrapped).
This tool currently support being built with the Serenity Clang toolchain or the lagom Clang toolchain (in which case it won't be able to verify Serenity-only applications)
Building & Running with the Serenity toolchain
First build Serenity with the Clang toolchain for x86_64:
./Meta/serenity.sh build x86_64 Clang
Then build the tool with:
cmake -GNinja -B build
cmake --build build
Then run the tool with:
src/main.py -b <path to serenity>/Build
Building & Running with the Lagom toolchain
First build the Serenity lagom applications with:
./Meta/serenity.sh build lagom
Then build the tool with:
cmake -GNinja -DLAGOM_BUILD=ON -B build
cmake --build build
Then run the tool with:
src/main.py -l -b <path to serenity>/Build