This means we can instantiate them for pseudo-elements, which don't have
an associated Element. They all pass it to their parent as a
`Layout::Node*` and handle a lack of `layout_node()` already so this
won't affect any functionality.
There were a couple issues here:
1. The line feed should only be appended once, rather than one per
string.
2. The new_strings list of strings was unused (we were creating the new
list, then passing the old list to Document.write).
This necessitated making HTMLParser ref-counted, and having it register
itself with Document when created. That makes it possible for scripts to
add new input at the current parser insertion point.
There is now a reference cycle between Document and HTMLParser. This
cycle is explicitly broken by calling Document::detach_parser() at the
end of HTMLParser::run().
This is a huge progression on ACID3, from 31% to 49%! :^)
This patch adds a map of Layout::Node to FormattingState::NodeState.
Instead of updating layout nodes incrementally as layout progresses
through the formatting contexts, all updates are now written to the
corresponding NodeState instead.
At the end of layout, FormattingState::commit() is called, which
transfers all the values from the NodeState objects to the Node.
This will soon allow us to perform completely non-destructive layouts
which don't affect the tree.
Note that there are many imperfections here, and still many places
where we assign to the NodeState, but later read directly from the Node
instead. I'm just committing at this stage to make subsequent diffs
easier to understand.
The purpose of this new object will be to keep track of various states
during an ongoing layout.
Until now, we've been updating layout tree nodes as we go during layout,
which adds an invisible layer of implicit serialization to the whole
layout system.
My idea with FormattingState is that running layout will produce a
result entirely contained within the FormattingState object. At the end
of layout, it can then be applied to the layout tree, or simply queried
for some metrics we were trying to determine.
When doing subtree layouts to determine intrinsic sizes, we will
eventually be able to clone the current FormattingState, and run the
subtree layout in isolation, opening up opportunities for parallelism.
This first patch doesn't go very far though, it merely adds the object
as a skeleton class, and makes sure the root BFC has one. :^)
This implements basic support for dynamic markup insertion, adding
* Document::open()
* Document::write(Vector<String> const&)
* Document::writeln(Vector<String> const&)
* Document::close()
The HTMLParser is modified to make it possible to create a
script-created parser which initially only contains a HTMLTokenizer
without any data. Aditionally the HTMLParser::run method gains an
overload which does not modify the Document and does not run
HTMLParser::the_end() so that we can reenter the parser at a later time.
Furthermore all FIXMEs that consern the insertion point are implemented
wich is defined in the HTMLTokenizer. Additionally the following
member-variables of the HTMLParser are now exposed by getter funcions:
* m_tokenizer
* m_aborted
* m_script_nesting_level
The HTMLTokenizer is modified so that it contains an insertion
point which keeps track of where the next input from the Document::write
functions will be inserted. The insertion point is implemented as the
charakter offset into m_decoded_input and a boolean describing if the
insertion point is defined. Functions to update, check and {re}store the
insertion point are also added.
The function HTMLTokenizer::insert_eof is added to tell a script-created
parser that document::close was called and HTMLParser::the_end() should
be called.
Lastly an explicit default constructor is added to HTMLTokenizer to
create a empty HTMLTokenizer into which data can be inserted.
This also adds a variant of {add,remove}_event_listener called
{add,remove}_event_listener_with_options.
This is used internally to perform {add,remove}_event_listener with a
default constructed options struct. It was done like this because
default constructing the Variant with the options struct requires the
struct defintions to be present, which requires us to include
AbortSignal.h, which would cause a circular include as AbortSignal.h
includes EventTarget.h.
This is not a complete implementation of API, since we're also supposed
to accept an options dictionary as the third argument. However, a lot of
web content uses the boolean variant, and it's trivial to support.
I can't imagine how this happened, but it seems we've managed to
conflate the "event listener" and "EventListener" concepts from the DOM
specification in some parts of the code.
We previously had two things:
- DOM::EventListener
- DOM::EventTarget::EventListenerRegistration
DOM::EventListener was roughly the "EventListener" IDL type,
and DOM::EventTarget::EventListenerRegistration was roughly the "event
listener" concept. However, they were used interchangeably (and
incorrectly!) in many places.
After this patch, we now have:
- DOM::IDLEventListener
- DOM::DOMEventListener
DOM::IDLEventListener is the "EventListener" IDL type,
and DOM::DOMEventListener is the "event listener" concept.
This patch also updates the addEventListener() and removeEventListener()
functions to follow the spec more closely, along with the "inner invoke"
function in our EventDispatcher.
ACID3 test page throws exception about document.write. Let's at least
get rid of it by defining these stubs.
I added document.writeln too because it is similar.
getClientRects supposed to return a list of bounding DOMRect
for each box fragment of Element's layout, but most elements have
only one box fragment, so implementing it with getBoundingClientRect
is useful.
BFC currently has a number of architectural issues due to it being
responsible for setting the dimensions of the BFC root.
This patch moves the logic for setting up the ICB from BFC to Document.
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.
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 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