An svg layout element without a `SVGSVGElement` ancestor caused a failed
assertion before, because the svg context does not exist when `paint()`
is called
Change all the places that were including the deprecated parser, to
include the new one instead, and then delete the old parser code.
`ParentNode::query_selector[_all]()` now treat their input as a
comma-separated list of selectors, instead of just one, and return
elements that match any of the selectors in that list. This is according
to these specs:
- querySelector/querySelectorAll:
https://dom.spec.whatwg.org/#ref-for-dom-parentnode-queryselector%E2%91%A0
- selector matching algorithm:
https://www.w3.org/TR/selectors-4/#match-against-tree
Problem:
- New `any_of` implementation takes the entire container so the user
does not need to pass explicit begin/end iterators. This is unused
except is in tests.
Solution:
- Make use of the new and more user-friendly version where possible.
This is three small, related changes:
1. Element::has_attribute() now returns true if the attribute exists but
has no value. (eg, `<div foo />` -> `has_attribute("foo")`)
2. SelectorEngine::matches_attribute() now makes sure there is a first
segment before comparing it, fixing a crash.
3. CSS::Parser now converts attribute names in attribute selectors to
lowercase, to match the expectations of the rest of the system.
Converting to lowercase is not always correct, depending on language,
but since we only currently support HTML, and that expects them to be
case-insensitive, it is fine for now.
The end goal is to make the PseudoClass::not_selector be a Selector
instead of a String that is repeatedly re-parsed. But since Selector
contains a Vector of ComplexSelectors, which each have a Vector of
SimpleSelectors, it's probably a good idea to not be passing them
around by value anyway. :^)
The new one is the same as the old one, just in the new Parser's
source files. This isn't the most elegant solution but it seemed
like the best option. And it's all temporary, after all.
These were an ad-hoc way to implement special behaviour when reading or
writing to specific object properties. Because these were effectively
replaced by the abillity to override the internal methods of Object,
they are no longer needed.
Previously it was not doing so, and some code relied on this not being
the case.
In particular, set_caption, set_t_head and set_t_foot in
HTMLTableElement relied on this. This commit is not here to fix this,
so I added an assertion to make it equivalent to a reference for now.
Nodes implementing the adoption steps can modify the passed in
document, for example HTMLTemplateElement does so to adopt it's
contents into the new document.
This will be used in HTMLTemplateElement later to clone template
contents.
This makes the clone functions non-const in the process, as the cloning
steps can have side effects.
It was directly creating a new Element object instead of creating the
appropriate element.
For example, document.body.cloneNode(true) would return an Element
instead of an HTMLBodyElement.
This is a huge patch, I know. In hindsight this perhaps could've been
done slightly more incremental, but I started and then fixed everything
until it worked, and here we are. I tried splitting of some completely
unrelated changes into separate commits, however. Anyway.
This is a rewrite of most of Object, and by extension large parts of
Array, Proxy, Reflect, String, TypedArray, and some other things.
What we already had worked fine for about 90% of things, but getting the
last 10% right proved to be increasingly difficult with the current code
that sort of grew organically and is only very loosely based on the
spec - this became especially obvious when we started fixing a large
number of test262 failures.
Key changes include:
- 1:1 matching function names and parameters of all object-related
functions, to avoid ambiguity. Previously we had things like put(),
which the spec doesn't have - as a result it wasn't always clear which
need to be used.
- Better separation between object abstract operations and internal
methods - the former are always the same, the latter can be overridden
(and are therefore virtual). The internal methods (i.e. [[Foo]] in the
spec) are now prefixed with 'internal_' for clarity - again, it was
previously not always clear which AO a certain method represents,
get() could've been both Get and [[Get]] (I don't know which one it
was closer to right now).
Note that some of the old names have been kept until all code relying
on them is updated, but they are now simple wrappers around the
closest matching standard abstract operation.
- Simplifications of the storage layer: functions that write values to
storage are now prefixed with 'storage_' to make their purpose clear,
and as they are not part of the spec they should not contain any steps
specified by it. Much functionality is now covered by the layers above
it and was removed (e.g. handling of accessors, attribute checks).
- PropertyAttributes has been greatly simplified, and is being replaced
by PropertyDescriptor - a concept similar to the current
implementation, but more aligned with the actual spec. See the commit
message of the previous commit where it was introduced for details.
- As a bonus, and since I had to look at the spec a whole lot anyway, I
introduced more inline comments with the exact steps from the spec -
this makes it super easy to verify correctness.
- East-const all the things.
As a result of all of this, things are much more correct but a bit
slower now. Retaining speed wasn't a consideration at all, I have done
no profiling of the new code - there might be low hanging fruits, which
we can then harvest separately.
Special thanks to Idan for helping me with this by tracking down bugs,
updating everything outside of LibJS to work with these changes (LibWeb,
Spreadsheet, HackStudio), as well as providing countless patches to fix
regressions I introduced - there still are very few (we got it down to
5), but we also get many new passing test262 tests in return. :^)
Co-authored-by: Idan Horowitz <idan.horowitz@gmail.com>
We must hook `on_call_stack_emptied` after the interpreter was created,
as the initialization of the WindowsObject can invoke some internal
calls, which will eventually lead to this hook being called without
`m_interpreter` being fully initialized yet.
This method builds a JSON object representing the full state of the
DOM tree.
The JSON that is built will be used for building the DOM Inspector
widget for the OutOfProcessWebView.
The WebIDL spec specifies a few "simple" exception types in addition to
the DOMException type, let's support all of those.
This allows functions returning ExceptionOr<T> to throw regular
javascript exceptions (as limited by the webidl spec) by returning a
`DOM::SimpleException { DOM::SimpleExceptionType::T, "error message" }`
which is pretty damn cool :^)
Adds support for the :active pseudo-class for hyperlinks (<a> tags
only).
Also, since it was very similar to :focus and an element having a
focused state was already implemented, I went ahead and implemented
that pseudo-class too, although I cannot come up with a working
example to validate it.
This counter is increased each time a synchronous execution sequence
completes, and will allow us to emulate the abstract operations
AddToKeptObjects & ClearKeptObjects efficiently.
Previously, AK::Function would accept _any_ callable type, and try to
call it when called, first with the given set of arguments, then with
zero arguments, and if all of those failed, it would simply not call the
function and **return a value-constructed Out type**.
This lead to many, many, many hard to debug situations when someone
forgot a `const` in their lambda argument types, and many cases of
people taking zero arguments in their lambdas to ignore them.
This commit reworks the Function interface to not include any such
surprising behaviour, if your function instance is not callable with
the declared argument set of the Function, it can simply not be
assigned to that Function instance, end of story.
This replaces ctype.h with CharacterType.h everywhere I could find
issues with narrowing conversions. While using it will probably make
sense almost everywhere in the future, the most critical places should
have been addressed.
Our "frame" concept very closely matches what the web specs call a
"browsing context", so let's rename it to that. :^)
The "main frame" becomes the "top-level browsing context",
and "sub-frames" are now "nested browsing contexts".
This introduces methods to increment and decrement the cursor position.
This is non-trivial as the cursor position is specified in bytes rather
than codepoints. Thus, it sometimes needs to be incremented or
decremented by more than one, depending on the codepoint to "jump over".
Because the cursor blink cycle needs to be reset after moving the
cursor, methods calling the ones in DOM::Position are implemented in
Frame. Furthermore, this allows the cursor_position() getter to stay
const. :^)
Additionally, it adds a offset_is_at_end_of_node() method which checks
if the current offset points to the end of the node.
This modifies the Document class to use Optional<String> for the
encoding. If the encoding is unknown, the Optional will not have a
value. It also implements the has_encoding() and encoding_or_default()
instance methods, the latter of which will return "UTF-8" as a fallback
if no encoding is present.
The usage of Optional<String> instead of the null string is part of an
effort to explicitly indicate that a string could not have a value.
This also modifies the former callers of encoding() to use
encoding_or_default(). Furthermore, the encoding will now only be set if
it is actually known, rather than just guessed by earlier code.
For regular elements, this is just the qualified name.
However, for HTML elements in HTML documents, it is the qualified name
uppercased.
This is used by jQuery to determine the document is an HTML document.
Not having this made jQuery assume the document was XML, causing
weird behaviour.
To do this, an internal string of qualified name is created.
This is to prevent constantly regenerating it. This is allowed by
the spec.
This is the same for the HTML-uppercased qualified name.
LibWeb is now responsible for logging unhandled exceptions itself,
which means set_should_log_exceptions() is no longer used and can be
removed. It turned out to be not the best option for web page exception
logging, as we would have no indication regarding whether the exception
was later handled of not.
Instead of having to run queued promise jobs in LibWeb in various
places, this allows us to consolidate that into one function - this is
very close to how the spec describes it as well ("at some future point
in time, when there is no running execution context and the execution
context stack is empty, the implementation must [...]").
Eventually this will also be used to log unhandled exceptions, and
possibly other actions that require JS execution to have ended.