Previously most of the calculations for `object-fit` and
`object-position` were based on device pixels, meaning that images would
render differently based on zoom and DPI settings. Instead those
calculations now use css pixels and only the final draw-call is based
on device-pixels.
When an element is displayed as table, an anonymous table wrapper box
needs to be created for it. Among others, the position property of the
table element is then applied to the anonymous table wrapper box
instead. If the table happens to be positioned absolutely, the table
wrapper box may become the containing block for absolutely positioned
elements inside the table.
In the original code however, anonymous layout nodes were excluded from
becoming the containing block for an absolutely positioned element.
Because of this, the containing block was calculated to be the first
suitable parent block of the table wrapper box.
This incorrect containing block would result in a crash later on when
trying to size the absolutely positioned element inside the table. To
prevent this crash, the anonymous table wrapper box is now allowed to
become the containing block for absolutely positioned elements inside
a table.
The definition of containing block for an absolutely positioned element
in the spec does not mention anything about skipping anonymous boxes.
Additionally the rules for absolute positioning of tables
(https://www.w3.org/TR/css-tables-3/#abspos-boxes-in-table-root) imply
that a table wrapper box is indeed able to be the containing block for
absolutely positioned elements.
The "with" statement is its own token (TokenType::With), and thus would
fail to parse as an identifier. We've already asserted that the token
we are parsing is "with" or "assert", so just consume it.
It is currently implemented as a member of CyclicModule. However, as the
spec indicates, this must be invokable with non-CyclicModule modules. In
several of the call sites, we are blindly casting to a CyclicModule;
this will fail for e.g. JSON modules.
Linking a module has assertions about the module's state, namely that
the state is not "new". The state remains "new" if loading the module
has failed. See: https://tc39.es/ecma262/#figure-module-graph-missing
In any case, this exception causes a loading failure, which results
in A's [[Status]] remaining new.
So we must propagate that failure, instead of blindly moving on to the
linking steps.
We currently have a fair amount of code of the form:
if (is<Child>(parent)) {
auto& child = static_cast<Child&>(parent);
if (child.foo()) {
}
}
This new cast allows us to instead write code of the form:
if (auto* child = as_if<Child>(parent); child && child->foo()) {
}
N.B. The name "as_if" was chosen because we are considering renaming
verify_cast to "as".
Co-authored-by: Tim Ledbetter <tim.ledbetter@ladybird.org>
Interestingly, the spec has a note saying:
> window.postMessage() performs StructuredSerializeWithTransfer on
> its arguments, but is careful to do so immediately, inside the
> synchronous portion of its algorithm. Thus it is able to use the
> algorithms without needing to prepare to run script and prepare
> to run a callback.
But there is no note about the deserialization steps. In any case, we do
need callbacks enabled here.
...Which doesn't do anything given start() itself doesn't do anything,
but this is a subtle enough point of the spec that it seems worthwhile
to implement now for whenever this does become meaningful.
For example, running `alert(1)` will pause the event loop, during which
time no JavaScript should execute. This patch extends this disruption to
microtasks. This avoids a crash inside the microtask executor, which
asserts the JS execution context stack is empty.
This makes us behave the same as Firefox in the following page:
<script>
queueMicrotask(() => {
console.log("inside microtask");
});
alert("hi");
</script>
Before the aforementioned assertion was added, we would execute that
microtask before showing the alert. Firefox does not do this, and now
we don't either.
Implements idea described in
https://docs.google.com/document/d/1vEW86DaeVs4uQzNFI5R-_xS9TcS1Cs_EUsHRSgCHGu8
Invalidation sets are used to reduce the number of elements marked for
style recalculation by collecting metadata from style rules about the
dependencies between properties that could affect an element’s style.
Currently, this optimization is only applied to style invalidation
triggered by class list mutations on an element.
We were previously crashing when invoking 'scroll to the fragment' on
such documents as it was unable to find the active document. This is
as a result of our AD-HOC implementation not setting up the document
fully to mark it is active before running the parser.
Fixes a crash on https://tweakers.net.
This is sub-optimal but let's rebuild the whole tree for now, since this
case gets quite complicated and there are more valuable things to chase
after first.
Thanks to Gingeh for the reduced test case!
This updates our local ICU overlay port to use ICU 76.1. This includes
Unicode 16 and CLDR 46.
Upstream vcpkg is not able to supply versions past 74 yet due to various
dependency issues, but we are able to use this version ourselves. The
overlay port now includes a patch to revert ICU's dependence on autoconf
2.72 for now, as this version is not yet available on all systems.
All of the test changes were cross-referenced with Firefox to ensure
correctness.
In ICU 76, the default was changed from "arab" to "latn". See:
c149724509
The whole point of these tests was to use a non-Latin numbering system.
This patch ensures that is the case to make following patches easier to
grok.
This separates the StringBuilder constructor into 2 constructors. This
essentially allows forming code of the following pattern:
StringBuilder foo() { return {}; }
Otherwise, we would get the following compiler error:
chosen constructor is explicit in copy-initialization
Due to the explicitness of the StringBuilder constructor.
This is required for an upcoming update to ICU 76, where we use our
StringBuilder in templated ICU code.
These common cases now cause us to invalidate the layout tree starting
at the relevant parent node instead of invalidating the entire tree.
- DOM node insertion
- DOM node removal
- innerHTML setter
- textContent setter
This makes a lot of dynamic content much faster. For example, demos
on shadertoy.com go from ~18 fps to ~28 fps on my machine.
DOM nodes now have two additional flags:
- Needs layout tree update
- Child needs layout tree update
These work similarly to the needs-style-update flags, but instead signal
the need to rebuild the corresponding part of the layout tree.
When a specific DOM node needs a layout tree update, we try to create
a new subtree starting at that node, and then replace the subtree in the
old layout tree with the newly created subtree.
This required some refactoring in TreeBuilder so that we can skip over
entire subtrees during a tree update.
Note that no partial updates happen yet (as of this commit) since we
always invalidate the full layout tree still. That will change in the
next commit.
Instead just update the existing wrapper with computed values from the
table box, to insure that upside-down "inheritance" works as expected.
This allows table fixup to run on partially updated layout trees without
adding a new layer of unnecessary wrappers every time.
While PendingPullIntos are typically visted by their controller there
were some cases that we were removing those references from the
controller and storing them in a SinglyLinkedList on the stack which
is not safe.
Instead, make PendingPullInto a GC::Cell type, which also allows us
to remove an awkward copy of the struct where the underlying reference
was previously being destroyed.