This allows us to use this:
```cpp
auto header = TRY_OR_RETURN_OOM(realm,
Infrastructure::Header::from_string_pair(name, value));
```
Instead of the somewhat unwieldly:
```cpp
auto header = Infrastructure::Header {
.name = TRY_OR_RETURN_OOM(realm, ByteBuffer::copy(name.bytes())),
.value = TRY_OR_RETURN_OOM(realm, ByteBuffer::copy(value.bytes())),
};
```
Positioned descendants are now handled entirely by paint_internal()
so we can just skip over positioned children in paint_descendants().
This avoids drawing the same boxes multiple times.
This "worked" before because all positioned elements would create their
own stacking context. When we stopped doing this, there was nobody to
actually paint positioned descendants with `z-index: auto`.
This patch splits up steps 8 and 9 of the paint order algorithm and
implements step 8 as a paint tree traversal. There's more to step 8 than
I've implemented here, so I've left a FIXME for our future selves.
Since positioned elements no longer automatically create stacking
contexts, we can't rely on this assumption when painting descendants of
a stacking context.
In this commit, we fix an issue that manifested as a failure to
Gfx::Painter::restore() in the "Overlay" paint phase. What happened was
that a CSS clip was being applied in the "Background" paint phase, and
then unapplied in the "Overlay" phase. Due to bogus checks in
paint_descendants(), the "Background" phase never ran for positioned
elements, but the "Overlay" phase did.
The check for positioned elements was bogus in the first place and had
never actually worked before, since we would always skip over positioned
descendants due to them having stacking contexts.
We were mistakenly creating stacking contexts for all elements with
non-static CSS position.
For `absolute` and `relative`, we should only create stacking contexts
if the `z-index` value is something other than `auto`.
This makes it possible to click the cookie on Cookie Clicker. :^)
Since our hit testing mechanism gives you the Paintable under the mouse
cursor, we can't just give up if that paintable doesn't have a
corresponding DOM node. That meant that generated content like pseudo-
elements didn't generate mouse events at all.
Fix this by making a dom_node_for_event_dispatch() helper function that
finds a suitable DOM node when given a paintable. This first cut is very
naive, and there's probably more we should do, but we have to start
somewhere. :^)
Because the result will be a float anyway get rid of the int parsing.
Also the grammar of SVG numbers matches the double parser grammar except
it can't have a sign but that should have been checked by the caller.
This could potentially be sped up by tracking the up to three different
ranges of characters known to be digits. This would save the double
parser from checking whether these are digits and because it has the
size it can use the fast parsing method.
Because strtod need to set ERANGE and track the last character we have
to check the resulting value. We also have to check for nan and inf in
strtod itself as the new double parser doesn't accept that as floating
points.
This (and still some other methods) just say Expectation error leaving
the user completely in the dark whether the method threw at all.
And since we have nice function printing now we can just toString the
function since most are lambda's.
The implementations for these methods is manually defined in the .cpp
file for `int` and `float`, meaning that other `T` values would fail -
but only once we got to the linking stage. This patch makes the error
happen much earlier, so it's more obvious.
Putting the implementations in the .cpp file meant that they only
existed for `IntRect` and `FloatRect`, since those were instantiated at
the bottom of the file. Now they work for other types. :^)
A couple of places in WindowServer had to be modified to disambiguate
between the two `Rect::intersected()` overloads.
Co-authored-by: davidot <davidot@serenityos.org>
To use the `GET /session/{id}/element/{id}/css/{property name}`
WebDriver endpoint, two new IPC calls through the Browser are
implemented:
- get_active_documents_type returns the type of the active document,
which is either "xml" or "html"
- get_computed_value_for_element returns the computed CSS value (as
String) for the given element and CSS property name
It's potentially unsafe to access `m_root` in the destructor since it
may have been swept, so move unregistration of the NodeIterator into a
GC finalizer instead.
It's not safe to unregister ImageBox from the browsing context in the
destructor (since the browsing context may have already been swept and
destroyed).
Now that the layout tree is also GC-allocated, we can't be messing with
it from the DOM::Node destructor. Move everything to a GC finalizer
so we know it runs before the GC sweep phase.
Doing things in the destructor of a GC-allocated object isn't always
safe, in case it involves accessing other GC-allocated objects.
If they were already swept by GC, we'd be poking into freed memory.
This patch adds a separate finalization pass where GC calls finalize()
on every unmarked cell that's about to be deleted.
It's safe to access other GC objects in finalize(), even if they're
also unmarked.
Now that both the layout tree and browsing context are GC-allocated,
we can formalize their relationship a bit better by having layout
nodes keep a NonnullGCPtr to the browsing context.
This makes the previously-indirect link direct, removing an unpleasant
"how do we know the browsing context is alive" question when accessing
it from the layout tree.
This caused `Object.getOwnPropertyNames(window)` to throw, as the
`this` value is `Object`.
All users of document_tree_child_browsing_context_count call it on an
existing Window impl, including WP::internal_own_property_keys, so
getting the impl from the JS VM is not necessary.
Since SafeFunction strongly protects all of its captures, we can't
capture `this` when activating an event handler since that creates a
reference cycle and we end up leaking the entire world.
This removes a set of complex reference cycles between DOM, layout tree
and browsing context.
It also makes lifetimes much easier to reason about, as the DOM and
layout trees are now free to keep each other alive.
(And BrowsingContextGroup had to come along for the ride as well.)
This solves a number of nasty reference cycles between browsing
contexts, history items, and their documents.
This fixes an issue where GC would kill the internal realm if it ran at
the wrong time during startup. Found by aggressively GC'ing between
every allocation.
This prevents a reference cycle between a HTMLParser opened via
document.open() and the document. It was one of many things keeping
some documents alive indefinitely.
Due to the way we lazily construct prototypes and constructors for web
platform interfaces, it's possible for nested GC allocation to occur
while GC objects have been allocated but not fully constructed.
If the garbage collector ends up running in this state, it may attempt
to call JS::Cell::visit_edges() on an object whose vtable pointer hasn't
been set up yet.
This patch works around the issue by deferring GC while intrinsics are
being brought up. Furthermore, we also create a dummy global object for
the internal realm, and populate it with intrinsics. This works around
the same issue happening when allocating something (like the default UA
stylesheets) in the internal realm.
These solutions are pretty hacky and sad, so I've left FIXMEs about
finding a nicer way.
We were taking AK::Function and then passing them along to
NativeFunction, which takes a SafeFunction. This works, since
SafeFunction will transparently wrap AK::Function in a CallableWrapper
when assigned, but it was causing us to accumulate thousands of
pointless wrappers around direct function pointers.
By using SafeFunction at every step of the setup call chain, we no
longer create any CallableWrappers for the majority of native functions
in LibJS. Also, the number of heap-registered SafeFunctions in a new
realm goes down from ~5000 to 5. :^)
Instead of storing two JS::Handles into the DOM, we can combine them
into a single one.
If the layout node is anonymous, m_dom_node points to the DOM::Document.
Otherwise, m_dom_node points to the associated DOM node.
The anonymous state is moved to an m_anonymous boolean member.
This cuts the number of JS::Handles created by the layout tree in half
(and shrinks Layout::Node by 8 bytes).
When a new document becomes the active document of a browsing context,
we now notify the old document, allowing it to tear down its layout
tree. In the future, there might be more cleanups we'd like to do here.
Capturing a WeakPtr to a GC-allocated object in a JS::SafeFunction is
basically pointless, since the SafeFunction mechanism will then keep
the object alive anyway.
These functions were previously ad-hoc and returned the active
document's window. They now correctly teturn the browsing context's
WindowProxy instead.
According to the OpenGL 2.0 spec § 2.8, the data for each attribute type
pointer is normalized according to the type. The only exception to this
is `glVertexAttribPointer` which accepts a `normalized` parameter, but
we have not yet implemented that API.
According to the spec, enabling the client-side vertex array should
behave as if `glVertex` is executed after all other states such as the
normal, color, etc. have changed. We were not changing these states if
the client-side vertex array was disabled which probably does not affect
a lot of applications, but this seems like the correct thing to do. :^)
We were invoking `frac_int_range` twice to get the `alpha` and `beta`
values to interpolate between 4 texels, but these call into
`floor_int_range` again. Let's not repeat the work.
We were mistakenly treating these as `for (x of obj)`. By reorganizing
the code a little bit, we actually support both kinds of iteration with
less duplication. :^)
Fixes 17 tests in test262.
Let's not incur the cost of a synchronous conversion to UTF-8 for all
the legacy static properties after running a regular expression.
The SunSpider subtest regexp-dna goes from taking ~25 sec to ~0.7 sec
on my machine.
The optimization passes are not stable, which makes test262 flaky.
Address this by introducing a new OptimizationLevel::None and making it
the default.
This removes all the flakiness from test262 in my testing.
We can enable optimizations by default again once they have been made
stable. :^)
`index + 1` was not correct. For example, if the body has two bytes, we
would consume the first byte and increment the index. We then add one
to the index and see it's equal to the size, so we take this one byte
and set the body result to it. The while loop would still continue and
we consume the second byte, adding it to the temporary buffer. We see
that the index is above the size, so we don't update the body, dropping
the last byte on the floor.
This extends the IPC calls `get_document_element` and
`query_selector_all` to be usable by the WebDriver. For this the
`WebDriverConnection` provides the same interfaces and takes care of
routing the data through the Browser.
In the fgetc function, a fix was already in place but was clunky. A real
proper solution is to use an unsigned char instead of a char when
returning the value, so an implicit cast is happening based on the
assumption that the value is unsigned, so if the variable contained 0xff
it won't be treated as -1, but as unsigned 0xff, so the result int will
be 0xff and not -1.
The same solution is applied to the fgetc_unlocked function as well.
When sizing grid children we now also check whether
calculate_min_content_height() adds to the computed height. Previously
we were using the result of layout_inner() which led to zero height of
not specifically sized block level children.
This fixes a height issue with our GitHub page. The footer is now at
its place and is not hovering over other content anymore.
On Fedora Silverblue and other OSTree-based systems, /etc/localtime is
a symlink to /run/host/etc/localtime, which then points to the expected
zoneinfo file, e.g. ../usr/share/zoneinfo/Europe/Berlin.
By using realpath() instead of readlink() we can resolve the symlink
recursively and avoid falling back to UTC.
This ensures we have just one location for determining the time zone, so
that LibC and LibTimeZone will behave the same.
(Note the FIXME removed here is also in TimeZone::current_time_zone.)
Commit c3fd455 changed LibTimeZone to fall back to the system time zone
when we fail to parse the TZ environment variable. This behavior differs
from both our LibC and glibc; they abort parsing and default to UTC.
This changes LibTimeZone to behave the same way to avoid a very awkward
situation where some parts of the codebase thinks the timezone is UTC,
and others think the timezone is whatever /etc/timezone indicates.
We have logic for serenity_generated_sources which works well for source
files that are specified in GENERATED_SOURCES prior to calling
serenity_lib or serenity_bin. However, code generated with
invoke_generator, and the LibWeb generators do not always follow the
pattern of the IDL and GML files.
For the LibWeb generators, we can just add_dependencies to LibWeb at the
time we declare the generate_Foo custom target. However for LibLocale,
LibTimeZone, and LibUnicode, we don't have the name of the target
available, so export the name in a variable to set into
GENERATED_SOURCES.
To make this work for Lagom, we need to make sure that lagom_lib and
serenity_bin in Lagom/CMakeLists.txt call serenity_generated_sources on
the target.
This enables the Xcode generator on macOS hosts, at least for Lagom.
This is an editorial change in the Temporal spec.
See: https://github.com/tc39/proposal-temporal/commit/d83dcf0
Note that even though we already implement AvailableTimeZones for Intl,
I kept the existing implementation calling into LibTimeZone directly.
This gives us better debug output when analysing calls to `undefined`
and also fixes multiple test-js cases expecting an
`(evaluated from $Expression)` in the error message.
This also refactors out the generation of that string, to avoid code
duplication with the AST interpreter.
We assumed that by returning a char in the fgetc function that an
implicit cast is sufficient, but apparently if that char contains 0xff,
the result int will be -1 (0xFFFFFFFF). To ensure this does not happen,
let's do an explicit casting.
pthread_setname_np is a can of worms for portability. Linux, macOS,
and the BSDs all do it differently.
Also skip adding the tid as an inspectable Core::Object property on
systems where pthread_t is known to be a pointer.
According to the spec, pointers to client data need to be dereferenced
immediately when adding calls such as `glDrawElements` or
`glArrayElement` to a display list. We were trying to support display
lists for these calls but since they only invoke _other_ calls that also
support display lists, we can simply defer the display list
functionality to them.
This fixes the rendering of the ClassiCube port by cflip.
Previously we would draw all text, no matter what font type, as
Liberation Serif, which results in things like ugly character spacing.
We now have partial support for drawing Type 1 glyphs, which are part of
a PostScript font program. We completely ignore hinting for now, which
results in ugly looking characters at low resolutions, but gain support
for a large number of typefaces, including most of the default fonts
used in TeX.
A PDFFont can now be asked for its specific type and whether it is part
of the standard 14 fonts. It now also contains a method to draw a
glyph, which is stubbed-out for now.
This will be useful for the renderer to take into consideration when
drawing text, since we don't include replacements for the standard set
of fonts yet, but still want to make use of embedded fonts when
available.
Also do this for Shell.
This greatly simplifies the CMakeLists in Lagom, replacing many glob
patterns with a big list of libraries. There are still a few special
libraries that need some help to conform to the pattern, like LibELF and
LibWebView.
It also lets us remove essentially all of the Serenity or Lagom binary
directory detection logic from code generators, as now both projects
directories enter the generator logic from the same place.
By deferring to the CMakeLists in each of these libraries' directories,
we can get rid of a lot of curious GLOB patterns and list removals in
the Lagom CMakeLists.
This lets us remove a glob pattern from LibC, the DynamicLoader, and,
later, Lagom. The Kernel already has its own separate list of AK files
that it wants, which is only a subset of all AK files.
This changes the signature of LoadRequest::set_body() to take by value
and then use move semantics to move the contents of the ByteBuffer.
This is done to avoid the fallible copy constructor of ByteBuffer.