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.
Previously we would disable console debug messages on all non Serenity
platforms as it caused double printing on lagom `js`. This patch limits
this to the `js` utility, allowing LibWeb to print debug messages
regardless of the operating system :^)
When converting to UTC, the UTC AO first tries to disambiguate possible
time zone offsets for the given local time. When doing so, the
GetNamedTimeZoneEpochNanoseconds AO must *subtract* the found time zone
offset from the local time to convert to UTC. The same is performed
later in the UTC AO when returning the final UTC time (step 5).
This is an editorial change in the Temporal spec. See:
https://github.com/tc39/proposal-temporal/commit/1b051cc
Note that since Date's implementation of this AO uses Crypto bigints
rather than allocating JS bigints, this change has the fallout of
removing some unused VM parameters and adding an overload of the
IsValidEpochNanoseconds AO for use without a JS::BigInt.
This is a normative change in the ECMA-262 spec. See:
https://github.com/tc39/ecma262/commit/43fd5f2
For the most part, these AOs are hoisted from Temporal.
Note that despite being a normative change, the expectation is that
this change does not result in any behavior differences.
Add classes ExplicitTrackSizing and MetaGridTrackSize which will allow
for managing properties like auto-fill and minmax.
In the following CSS example there are 3 classes that will be used:
grid-template-column: repeat(auto-fill, minmax(50px, 1fr) 75px);
ExplicitTrackSizing - will contain the entire value. e.g.
repeat(auto-fill, minmax(50px, 1fr) 75px)
With a flag if it's a repeat, as well as references to the
MetaGridTrackSizes which is the next step down.
MetaGridTrackSize:
Contain the individual grid track sizes. Here there are two:
minmax(50px, 1fr) as well as 75px.
This way can keep track if it's a minmax function or not, and the
references to both GridTrackSizes in the case it is, or in just the one
if it is not.
GridTrackSize:
Is the most basic element, in this case there are three in total; two of
which are held by the first MetaGridTrackSize, and the third is held by
the second MetaGridTrackSize.
Examples: 50px, 1fr and 75px.
As it turns out, we sometimes query the intrinsic height of a box before
having fully resolved and/or constrained its containing block. Because
of this, we may enter intrinsic sizing with different amounts of
available width for the same box.
To accommodate this scenario, we now allow caching of multiple intrinsic
heights, separated by the amount of available width provided as input.
This colors a bit outside the lines of the specification, but the spec
doesn't offer a proper explanation for how descendants of a flex item
are supposed to have access to the flex item's main size for purposes
of percentage resolution.
The approach I came up with here was to take the hypothetical main size
of each flex item, and assign it as a temporary main size. This allows
percentage resolution in descendants to work against the pre-flexing
main size of items. This seems to match how other engines behave,
although it feels somewhat dirty. If/when we learn more about this,
we can come up with something nicer.
Print exceptions passed to `HTML::report_exception` in the JS console
Refactored `ExceptionReporter`: in order to report exception now
you need to pass the relevant realm in it. For passed `JS::Value`
we now create `JS::Error` object to print value as the error message.
We were using the available space in place of the stretch-fit size.
This was an oversight, and this patch fixes that. It's very possible
that this will uncover broken behavior elsewhere.
This property tells us how to lay out multi-line flex containers.
I implemented all modes except `space-between` and `space-around`.
Those are left as FIXMEs.
This ensures that we create a line box for content:"", which would
otherwise get pruned by the empty line cleanup in IFC.
The empty line box is important in this case, since it gives us a
reference point for measuring the automatic height of the IFC's
containing block. By having an empty line, we can now correctly measure
the impact of vertical margins on a generated box with content:""
and allow them to contribute to the block height.
When checking if a line box fragment "isn't just dumb inline content",
we were checking "is replaced or inline-block". What we really need to
be checking is "is replaced or inline-outside-but-not-flow-inside".
So now we check that.
This fixes an issue where inline-flex boxes were given incorrect extra
height due to being treated as regular text for purposes of line height
calculation.
Percentage heights are now considered definite when their containing
block has a definite height. This makes profile pictures have geometry
on Twitter. (We still don't load the images themselves though.)
8-bit PCM samples are unsigned, at least in WAV, so after rescaling them
to the correct range we also need to center them around 0. This fix
should make 8-bit WAVs have the correct volume of double of what it was
before, and also future-proof for all other unsigned PCM sample formats
we may encounter.
Currently, the Value class is essentially a "pImpl" wrapper around the
ValueImpl hierarchy of classes. This is a bit difficult to follow and
reason about, as methods jump between the Value class and its impl
classes.
This changes the Variant held by Value to instead store the specified
types (String, int, etc.) directly. In doing so, the ValueImpl classes
are removed, and all methods are now just concise Variant visitors.
As part of this rewrite, support for the "array" type is dropped (or
rather, just not re-implemented) as it was unused. If it's needed in the
future, support can be re-added.
This does retain the ability for non-NULL types to store NULL values
(i.e. an empty Optional). I tried dropping this support as well, but it
is depended upon by the on-disk storage classes in non-trivial ways.
This was being used as a default version argument in a couple of APIs,
so those need to change signature and the caller always needs to provide
a version.
This change implements a flood fill algorithm for the Bitmap class. This
will be leveraged by various Tools in PixelPaint. Moving the code into
Bitmap reduces the duplication of the algorithm throughout the
PixelPaint Tools (currently Bucket Tool and Wand Select).
The flood fill function requires you to pass in a threshold value (0 -
100) as well as a lambda for what to do when a pixel gets reached. The
lambda is provided an IntPoint representing the coordinates of the pixel
that was just reached.
The genericized lambda approach allows for a variety of things to be
done as the flood algorithm progresses. For example, the Bucket Tool
will paint each pixel that gets reached with the fill_color. The Wand
Select tool wont actually alter the bitmap itself, instead it uses the
reached pixels to alter a selection mask.
Even though this almost certainly wouldn't run properly even if we had
a working kernel for AARCH64 this at least lets us build all the
userland binaries.
The clipboard service hasn't been ported to user-based portals with
others services as it is needed at `GUI::Application` creation and thus
before the first login, as the `LoginServer` needs one.
This problem as been solved thanks to session-based portals, a clipboard
portal is now created at boot for the "login" session and another for
each "user" session.
With a user-based portal, the "login" portal would have needed to be
created for the `root` user, exposing us to security issues. It now, can
be owned by the `window` user.
This fixes the Serenity logo vanishing after scrolling on the 4th
birthday post.
The previous check did not account for any translation in the painter.
This now uses the painter's clip rect and translation to work out
if a rect is visible. It also makes use of `absolute_paint_rect()`
rather than `absolute_rect()` which can account for things like
box-shadows.
When in normal mode pressing Shift+D will delete from the current cursor
position to the end of the line. Leaving the cursor on the character
before where the cursor was when the deletion took place.
We previously put the generated headers in SOURCES, which did not mark
them as GENERATED (and did not produce a proper dependency).
This commit moves all generated headers into GENERATED_SOURCES, and
removes useless header SOURCES.
This refactors the solve_for_{top, bottom, height, etc} lambdas to use a
common solve_for lambda that takes the length to be solved as an
argument. This way some code duplication is removed.
Previously, some integer overflows and truncations were causing parsing
errors for 4K videos, with those fixed it can fully decode 8K video.
This adds a test to ensure that 4K video will continue to be decoded.
Note: There seems to be unexpectedly high memory usage while decoding
them, causing 8K video to require more than a gigabyte of RAM. (!!!)
The relevant RFC section from
https://www.rfc-editor.org/rfc/rfc7932#section-9.2
MSKIPBYTES * 8 bits: MSKIPLEN - 1, where MSKIPLEN is
the number of metadata bytes; this field is
only present if MSKIPBYTES is positive;
otherwise, MSKIPLEN is 0 (if MSKIPBYTES is
greater than 1, and the last byte is all
zeros, then the stream should be rejected as
invalid)
So when skip_bytes is zero we need to break and
re-align bytes.
Added the relevant test case that demonstrates this from:
https://github.com/google/brotli/blob/master/tests/testdata/x.compressed