The CSSOM spec tells us to potentially add up to three different IDL
attributes to CSSStyleDeclaration for every CSS property we support:
- A camelCased attribute, where a dash indicates the next character
should be uppercase
- A camelCased attribute for every -webkit- prefixed property, with the
first letter always being lowercase
- A dashed-attribute for every property with a dash in it.
Additionally, every attribute must have the CEReactions and
LegacyNullToEmptyString extended attributes specified on it.
Since we specify every property we support with Properties.json, we can
use that file to generate the IDL file and it's implementation.
We import it from the Build directory with the help of multiple import
base paths. Then, we add it to CSSStyleDeclaration via the mixin
functionality and inheriting the generated class in
CSSStyleDeclaration.
This allows us to specify multiple base paths to look for imported IDL
files in. This will allow us to import IDL files from sources and from
the Build directory (i.e. for generated IDL files).
We currently have 2 virtual methods to inform DOM::Element subclasses
when an attribute has changed, one of which is spec-compliant. This
patch removes the non-compliant variant.
Instead, smuggle it in as a `void*` private data and let Javascript
aware code cast out that pointer to a VM&.
In order to make this split, rename JS::Cell to JS::CellImpl. Once we
have a LibGC, this will become GC::Cell. CellImpl then has no specific
knowledge of the VM& and Realm&. That knowledge is instead put into
JS::Cell, which inherits from CellImpl. JS::Cell is responsible for
JavaScript's realm initialization, as well as converting of the void*
private data to what it knows should be the VM&.
NanBoxedValue is intended to be a GC-allocatable type which is not
specific to javascript, towards the effort of factoring out the GC
implementation from LibJS.
Attempt 2! Reverts 2a5dbedad4
This time, set up a different combinator when producing a relative
invalid selector rather than a standalone one. This fixes the crash.
Original description below for simplicity because it still applies.
---
Selectors like `:is(.valid, &!?!?!invalid)` need to keep the invalid
part around, even though it will never match, for a couple of reasons:
- Serialization needs to include them
- For nesting, we care if a `&` appeared anywhere in the selector, even
in an invalid part.
So this patch introduces an `Invalid` simple selector type, which simply
holds its original ComponentValues. We search through these looking for
`&`, and we dump them out directly when asked to serialize.
This gets rid of a couple FIXMEs and allows reusing the logic of
validating this field between different algorithms. While we're here,
expand its logic to match the constraints as outlined in RFC 7517.
LibWebView now knows how to launch RequestServer and ImageDecoderServer
without help from the UI, so let's move ownership of these services over
to LibWebView for de-duplication.
This was a silly mistake on my end and percentages values are not
covered by device-independent color space, so I had to add support for
srgb to run a WPT test that made me realize the mistake.
This makes the following test pass:
- css/css-color/predefined-002.html
It makes the following WPT tests pass:
- css/css-color/predefined-001.html
- css/css-color/xyz-003.html
- css/css-color/xyz-d50-003.html
- css/css-color/xyz-d50-004.html
- css/css-color/xyz-d65-003.html
Also we now render the reference of color-mix-currentcolor-nested-for-
color-property.html properly. Which means that it's now different from
the actual test, that is still rendered incorrectly. In other word, the
false positive for this test is now turned into a true negative.
Now that the heap has no knowledge about a JavaScript realm and is
purely for managing the memory of the heap, it does not make sense
to name this function to say that it is a non-realm variant.
The main motivation behind this is to remove JS specifics of the Realm
from the implementation of the Heap.
As a side effect of this change, this is a bit nicer to read than the
previous approach, and in my opinion, also makes it a little more clear
that this method is specific to a JavaScript Realm.
Selectors like `:is(.valid, &!?!?!invalid)` need to keep the invalid
part around, even though it will never match, for a couple of reasons:
- Serialization needs to include them
- For nesting, we care if a `&` appeared anywhere in the selector, even
in an invalid part.
So this patch introduces an `Invalid` simple selector type, which simply
holds its original ComponentValues. We search through these looking for
`&`, and we dump them out directly when asked to serialize.
We will want to re-inform WebContent of the system visibility state when
we create a new process after a crash. This changes the IPC to just send
the enum value directly, instead of a boolean, so that we can just store
that enum value directly on the ViewImplementation class.
These operations should still apply even if they are off screen, because
they affect painting of things outside of their bounding rectangles.
This commit makes us always apply these, regardless of if they are in
the visible region. However, if they are outside that region, we
replace them with simple clip-rect commands, which have the same
effect (not painting anything) but are cheaper than computing a full
mask bitmap.
The insertion steps for iframes were following an old version of the
spec, where it was checking if the iframe was "in a document tree",
which doesn't cross shadow root boundaries. The spec has since been
updated to check the shadow including root instead.
This is now needed for Cloudflare Turnstile iframe widgets to appear,
as they are now inserted into a shadow root.
Previously, the inclusive descendant, which is the node that
for_each_shadow_including_inclusive_descendant was called on, would not
have it's shadow root traversed if it had one.
This is because the shadow root traversal was in the `for` loop, which
begins with the node's first child. The fix here is to move the shadow
root traversal outside of the loop, and check if the current node is an
element instead.
While this does mean that we keep one copy of the stack info in the VM,
and another in the Heap; keeping a separate instance removes one more
instance of coupling between the heap and LibJS specific details.
There is definitely a possibility I am misunderstanding the reason
behind it - but this does not appear neccessary. The VM owns both the
string cache and Heap. On destruction, the VM should clear out both
the heap and its string cache.
While this is used in the implementation of Runtime objects itself, Heap
seems like a more appropriate home. This will also help in factoring out
the GC implementation into it's own library as the heap explicitly has
knowledge of WeakContainer.
When the cached value was not an accessor, it was simply ignored.
This is the value we really want, so we can just return it.
Shows up to 5x improvements on some benchmarks,
and 1.4x in general js-benchmarks.
Async functions whose promise is never resolved were leaking, since they
had a strong root JS::Handle on themselves.
This doesn't appear to actually be necessary, since the wrapper will be
kept alive as long as it's reachable (and if it's not reachable, nobody
is going to resolve/reject the promise either).
This fixes the vast majority of leaks on Speedometer, bringing memory
usage at the end of a full run from ~12 GiB to ~3 GiB.
This fixes an issue where a badly-timed garbage collection could swallow
a static field initializer.
Caught by running test262 in GC-on-every-allocation mode.
We were miscalculating the length of the buffer in pointer-sized chunks,
which is what the conservative root scan cares about.
This could cause some values to be prematurely garbage-collected.
This was preventing https://ubereats.com/ from fully loading, because
they are attempting to overwrite setItem. They seem to be trying to add
error logging to setItem if it throws, as all they do is add a
try/catch block that emits an error log to their monitoring service if
it throws.
However, because Storage is a legacy platform object with a named
property setter (setItem), it will call setItem with the stringified
version of the function. This is actually expected as per the spec,
Firefox (Gecko) and Epiphany (WebKit) does this too, but Chromium does
not as it actually overwrites the function with the new function and
does not store the stringified function.
The problem is that we had the LegacyOverrideBuiltIns flag accidentally
set, so it would return the stored string instead of the built-in
function (hence the name), then it would try and call it and throw a
"not a function" error. This prevented their JS from going any further.
This fix allows their UI to fully load and be fully interactive, though
it is quite slow at the moment!
This change removes the append_without_space, append_with_space,
prepend_without_space, and prepend_with_space functions from DOM::Node.
All those methods were added with the initial “Implement Accessible Name
and Description Calculation” commit in da5c918 and were only used in the
code related to accessible-name computation. But subsequent changes to
that code have removed all the calls to those functions — so now they’re
all completely unused.
This change ensures that when the aria-labelledby attribute is used, the
expected text from the element referenced in the aria-labelledby value
appears in the computed accessible name. Otherwise, without this change,
the expected text doesn’t appear in the computed accessible name.
This change fixes handling for substep ii of the “F. Name From Content”
step at https://w3c.github.io/accname/#step2F in the “Accessible Name
and Description Computation” spec — to correctly include any ::before
and ::after pseudo-element content in the computation of accessible
names. Otherwise, without this change, accessible names unexpectedly
don’t include that pseudo-element content.
This change implements the https://w3c.github.io/accname/#comp_append
step in the “Accessible Name and Description Computation” spec — so that
when an accessible name is computed from multiple sources in a document
subtree, the parts of the computed text are joined together with spaces.
Otherwise without this change, in accessible names computed from
multiple sources in a document subtree, the parts of the computed text
are unexpectedly run together, with no spaces between the parts.
This is really just a type alias for NonnullGCPtr<T>, but it provides
a way to have non-owning non-visited NonnullGCPtr<T> without getting
yelled at by the Clang plugin for catching GC errors.
We were previously dumping the address of the cell pointer instead of
the address of the cell itself. This was causing mysterious orphans
in GC dumps, and it took me way too long to figure this out.
compute_inset() was incorrectly retrieving the containing block size
because containing_block() is unaware of grid areas that form a
containing block for grid items but do not exist in the layout tree.
With this change, we explicitly pass the containing block into
compute_inset(), allowing it to correctly provide the containing block
sizes for grid items.
Explicitly pass containing block width in
resolve_vertical_box_model_metrics() instead of doing containing block
box lookup.
This is a part of refactoring towards removing containing_block() usage
that will allow us introduce partial layout.
The following syntax is valid:
```js
e?.example / 1.2
```
Previously, the `/` would be treated as a unterminated regex literal,
because it was calling the regular `consume` instead of
`consume_and_allow_division`.
This is what is done when parsing IdentifierNames in
parse_secondary_expression when a period is encountered.
Allows us to parse clients-main-[hash].js on https://ubereats.com/
We currently compile the Qt event loop files multiple times, for every
target which wants to use them. This patch moves these to LibWebView as
a central location to avoid this.
If available space is definite it should always match the size of the
containing block. Therefore, there is no need to do containing block
node lookup.
The inline capacity on ThreadEventQueue::Private::queued_events caused
us to reserve (and importantly, not initialize!) 2 KiB of stack memory
when entering ThreadEventQueue::process().
This was causing any leftover pointers to GC-allocated objects within
that memory range to keep those objects alive, even when all other
references were gone.