This patch introduces the StyleComputer::RuleCache, which divides all of
our (author) CSS rules into buckets.
Currently, there are two buckets:
- Rules where a specific class must be present.
- All other rules.
This allows us to check a significantly smaller set of rules for each
element, since we can skip over any rule that requires a class attribute
not present on the element.
This takes the typical numer of rules tested per element on Discord from
~16000 to ~550. :^)
We can definitely improve the cache invalidation. It currently happens
too often due to media queries. And we also need to make sure we
invalidate when mutating style through CSSOM APIs.
Previously we would re-run the entire CSS selector machinery for each
property resolved. Instead of doing that, we now resolve a final set of
custom property key/value pairs at the start of the cascade.
- Replace "auto" with "auto const" where appropriate.
- Remove an unused struct.
- Make sort_matching_rules() a file-local static function.
- Remove some unnecessary includes.
Our previous code roughly did this:
1. Generate a bitmap as large as the shadow would end up.
2. Paint a rectangle onto it.
3. Blur the whole bitmap.
4. Split it up and render each section.
This patch takes advantage of the fact that (aside from corners) each
horizontal or vertical strip of a box-shadow is identical to the
others, to generate and blur a much smaller bitmap - only large enough
for the four corners and 1px of central "side" in each direction. This
greatly reduces the memory footprint, and should also speed things up,
since there is much less to blur.
This initial implementation stubs out the WorkerGlobalScope,
WorkerLocation and WorkerNavigator classes. It doesn't take into account
all the things that actually need passed into the constructors for these
objects, nor the extra abstract operations that need to be performed on
them by the rest of the Browser infrastructure. However, it does create
bindings that compile and link :^)
While trying to get http://lite.duckduckgo.com to work in the Browser I
noticed that we kept on getting 400 (Bad Request) errors when you click
the "Search" button for a request.
After turning on `JOB_DEBUG` to see what headers we were sending it
turned out that we were actually setting `Content-Length` twice once
in LibWeb, and again when the request is handled by LibHTTP.
Since LibHTTP transparently handles this now, we can avoid it in LibWeb.
Before this, we were filling and stroking every <path>, whether they had
a fill/stroke color or not. We can avoid a bunch of unnecessary work by
checking if the color is transparent (also the case if unset) before
doing the painting work.
If there is no fill color, we also avoid making a copy of the path to
ensure that it's closed.
This is a naive-but-somewhat-functional initial implementation of
HTML Storage.
Note that there is no persistence yet, everything is in-process only,
and one local Storage object per origin.
This overrides the JS host hooks to follow the spec for queuing
promises, making/calling job callbacks, unhandled promise rejection
handling and FinalizationRegistry queuing.
This also allows us to drop the on_call_stack_emptied hook in
Document::interpreter().
This isn't perfect (especially the global object situation in
activate_event_handler), but I believe it's in a much more complete
state now :^)
This fixes the issue of crashing in prepare_for_ordinary_call with the
`i < m_size` crash, as it now uses the IDL callback functions which
requires the Environment Settings Object. The environment settings
object for the callback is fetched at the time the callback is created,
for example, WrapperGenerator gets the incumbent settings object for
the callback at the time of wrapping. This allows us to remove passing
in ScriptExecutionContext into EventTarget's constructor.
With this, we can now drop ScriptExecutionContext.
The new event target implementation requires us to downcast an
EventTarget to a FormAssociatedElement to check if the current Element
EventTarget has a form owner to setup a with scope for the form owner.
This also makes all form associated elements inherit from
FormAssociatedElement where it was previously missing.
https://html.spec.whatwg.org/#form-associated-element
The environment settings object is effectively the context a piece of
script is running under, for example, it contains the origin,
responsible document, realm, global object and event loop for the
current context. This effectively replaces ScriptExecutionContext, but
it cannot be removed in this commit as EventTarget still depends on it.
https://html.spec.whatwg.org/multipage/webappapis.html#environment-settings-object
We also pass whether the shadow goes inside or outside the element. Only
outer shadows are rendered currently, and inner ones may want to be
handled separately from them, as they will never interfere with each
other.
The pattern we've adopted for other multi-value properties is to run in
a loop like this, since that makes it easier to cater for values
appearing in different orders.
Since VM::exception() no longer exists this is now useless. All of these
calls to clear_exception were just to clear the VM state after some
(potentially) failed evaluation and did not use the exception itself.
This commit removes all exception related code:
Remove VM::exception(), VM::throw_exception() etc. Any leftover
throw_exception calls are moved to throw_completion.
The one method left is clear_exception() which is now a no-op. Most of
these calls are just to clear whatever exception might have been thrown
when handling a Completion. So to have a cleaner commit this will be
removed in a next commit.
It also removes the actual Exception and TemporaryClearException classes
since these are no longer used.
In any spot where the exception was actually used an attempt was made to
preserve that behavior. However since it is no longer tracked by the VM
we cannot access exceptions which were thrown in previous calls.
There are two such cases which might have different behavior:
- In Web::DOM::Document::interpreter() the on_call_stack_emptied hook
used to print any uncaught exception but this is now no longer
possible as the VM does not store uncaught exceptions.
- In js the code used to be interruptable by throwing an exception on
the VM. This is no longer possible but was already somewhat fragile
before as you could happen to throw an exception just before a VERIFY.
During the LengthPercentage split, I converted the individual-corner
`border-foo-bar-radius` properties to LengthPercentage but forgot
`border-radius` itself! Oops. Discord's CSS was doing `border-radius:
50%` a lot, so this cuts down on CSS parser spam.
This function was unnecessarily nested, which created a scenario where
we could get stuck in an infinite loop without advancing the
current_object pointer up the browsing context container chain.
If the mousedown event hits something with is_focusable()==true,
we now update the document's focused element *instead* of placing the
text cursor at the focusable element.
This allows you to begin editing input elements by clicking them.
This feels very hackish and we'll need to come up with something nicer.
The main deviation from the spec is that we don't have a straightforward
representation of the spec's "focusable area" concept.
I've left a bunch of FIXME's around for our future selves. :^)