2020-05-24 00:14:23 +02:00
|
|
|
/*
|
2024-10-04 13:19:50 +02:00
|
|
|
* Copyright (c) 2020-2022, Andreas Kling <andreas@ladybird.org>
|
2020-05-24 00:14:23 +02:00
|
|
|
*
|
2021-04-22 01:24:48 -07:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
2020-05-24 00:14:23 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
2023-05-28 15:04:40 +12:00
|
|
|
#include <LibGfx/Color.h>
|
2022-10-17 10:46:11 +02:00
|
|
|
#include <LibJS/Heap/Cell.h>
|
2026-02-11 09:20:13 +01:00
|
|
|
#include <LibWeb/DOM/FragmentSerializationMode.h>
|
2025-07-19 19:35:33 -07:00
|
|
|
#include <LibWeb/Export.h>
|
2020-07-28 19:18:23 +02:00
|
|
|
#include <LibWeb/HTML/Parser/HTMLTokenizer.h>
|
|
|
|
|
#include <LibWeb/HTML/Parser/ListOfActiveFormattingElements.h>
|
2026-04-12 13:31:30 +02:00
|
|
|
#include <LibWeb/HTML/Parser/ParserScriptingMode.h>
|
2020-07-28 19:18:23 +02:00
|
|
|
#include <LibWeb/HTML/Parser/StackOfOpenElements.h>
|
2024-10-20 19:39:50 +11:00
|
|
|
#include <LibWeb/MimeSniff/MimeType.h>
|
LibWeb: Replace spin_until in HTMLParser::the_end() with state machine
HTMLParser::the_end() had three spin_until calls that blocked the event
loop: step 5 (deferred scripts), step 7 (ASAP scripts), and step 8
(load event delay). This replaces them with an HTMLParserEndState state
machine that progresses asynchronously via callbacks.
The state machine has three phases matching the three spin_until calls:
- WaitingForDeferredScripts: loops executing ready deferred scripts
- WaitingForASAPScripts: waits for ASAP script lists to empty
- WaitingForLoadEventDelay: waits for nothing to delay the load event
Notification triggers re-evaluate the state machine when conditions
change: HTMLScriptElement::mark_as_ready, stylesheet unblocking in
StyleElementBase/HTMLLinkElement, did_stop_being_active_document, and
DocumentLoadEventDelayer decrements. NavigableContainer state changes
(session history readiness, content navigable cleared, lazy load flag)
also trigger re-evaluation of the load event delay check.
Key design decisions and why:
1. Microtask checkpoint in schedule_progress_check(): The old spin_until
called perform_a_microtask_checkpoint() before checking conditions.
This is critical because HTMLImageElement::update_the_image_data step
8 queues a microtask that creates the DocumentLoadEventDelayer.
Without the checkpoint, check_progress() would see zero delayers and
complete before images start delaying the load event.
2. deferred_invoke in schedule_progress_check():
I tried Core::Timer (0ms), queue_global_task, and synchronous calls.
Timers caused non-deterministic ordering with the HTML event loop's
task processing timer, leading to image layout tests failing (wrong
subtest pass/fail patterns). Synchronous calls fired too early during
image load processing before dimensions were set, causing 0-height
images in layout tests. queue_global_task had task ordering issues
with the session history traversal queue. deferred_invoke runs after
the current callback returns but within the same event loop pump,
giving the right balance.
3. Navigation load event guard (m_navigation_load_event_guard): During
cross-document navigation, finalize_a_cross_document_navigation step
2 calls set_delaying_load_events(false) before the session history
traversal activates the new document. This creates a transient state
where the parent's load event delay check sees the about:blank (which
has ready_for_post_load_tasks=true) as the active document and
completes prematurely.
2026-03-28 09:39:51 +01:00
|
|
|
#include <LibWeb/Platform/Timer.h>
|
2020-05-24 00:14:23 +02:00
|
|
|
|
2020-07-28 18:20:36 +02:00
|
|
|
namespace Web::HTML {
|
|
|
|
|
|
2025-10-23 20:44:10 -07:00
|
|
|
#define ENUMERATE_INSERTION_MODES \
|
|
|
|
|
__ENUMERATE_INSERTION_MODE(Initial) \
|
|
|
|
|
__ENUMERATE_INSERTION_MODE(BeforeHTML) \
|
|
|
|
|
__ENUMERATE_INSERTION_MODE(BeforeHead) \
|
|
|
|
|
__ENUMERATE_INSERTION_MODE(InHead) \
|
|
|
|
|
__ENUMERATE_INSERTION_MODE(InHeadNoscript) \
|
|
|
|
|
__ENUMERATE_INSERTION_MODE(AfterHead) \
|
|
|
|
|
__ENUMERATE_INSERTION_MODE(InBody) \
|
|
|
|
|
__ENUMERATE_INSERTION_MODE(Text) \
|
|
|
|
|
__ENUMERATE_INSERTION_MODE(InTable) \
|
|
|
|
|
__ENUMERATE_INSERTION_MODE(InTableText) \
|
|
|
|
|
__ENUMERATE_INSERTION_MODE(InCaption) \
|
|
|
|
|
__ENUMERATE_INSERTION_MODE(InColumnGroup) \
|
|
|
|
|
__ENUMERATE_INSERTION_MODE(InTableBody) \
|
|
|
|
|
__ENUMERATE_INSERTION_MODE(InRow) \
|
|
|
|
|
__ENUMERATE_INSERTION_MODE(InCell) \
|
|
|
|
|
__ENUMERATE_INSERTION_MODE(InTemplate) \
|
|
|
|
|
__ENUMERATE_INSERTION_MODE(AfterBody) \
|
|
|
|
|
__ENUMERATE_INSERTION_MODE(InFrameset) \
|
|
|
|
|
__ENUMERATE_INSERTION_MODE(AfterFrameset) \
|
|
|
|
|
__ENUMERATE_INSERTION_MODE(AfterAfterBody) \
|
2020-05-24 00:14:23 +02:00
|
|
|
__ENUMERATE_INSERTION_MODE(AfterAfterFrameset)
|
|
|
|
|
|
2025-07-19 19:35:33 -07:00
|
|
|
class WEB_API HTMLParser final : public JS::Cell {
|
2024-11-15 04:01:23 +13:00
|
|
|
GC_CELL(HTMLParser, JS::Cell);
|
|
|
|
|
GC_DECLARE_ALLOCATOR(HTMLParser);
|
2022-10-17 10:46:11 +02:00
|
|
|
|
2022-02-15 18:52:45 +00:00
|
|
|
friend class HTMLTokenizer;
|
|
|
|
|
|
2020-05-24 00:14:23 +02:00
|
|
|
public:
|
2021-09-25 23:15:48 +02:00
|
|
|
~HTMLParser();
|
2020-05-24 00:14:23 +02:00
|
|
|
|
2024-11-15 04:01:23 +13:00
|
|
|
static GC::Ref<HTMLParser> create_for_scripting(DOM::Document&);
|
|
|
|
|
static GC::Ref<HTMLParser> create_with_uncertain_encoding(DOM::Document&, ByteBuffer const& input, Optional<MimeSniff::MimeType> maybe_mime_type = {});
|
2026-04-12 13:31:30 +02:00
|
|
|
static GC::Ref<HTMLParser> create(DOM::Document&, StringView input, ParserScriptingMode, StringView encoding);
|
2021-05-12 10:47:12 +02:00
|
|
|
|
2024-02-18 12:45:53 -05:00
|
|
|
void run(HTMLTokenizer::StopAtInsertionPoint = HTMLTokenizer::StopAtInsertionPoint::No);
|
2025-08-29 13:02:52 +01:00
|
|
|
void run(URL::URL const&, HTMLTokenizer::StopAtInsertionPoint = HTMLTokenizer::StopAtInsertionPoint::No);
|
2020-05-24 00:14:23 +02:00
|
|
|
|
2024-11-15 04:01:23 +13:00
|
|
|
static void the_end(GC::Ref<DOM::Document>, GC::Ptr<HTMLParser> = nullptr);
|
2023-12-19 12:51:34 +00:00
|
|
|
|
2020-07-26 19:37:56 +02:00
|
|
|
DOM::Document& document();
|
2024-06-25 20:55:58 +01:00
|
|
|
enum class AllowDeclarativeShadowRoots {
|
|
|
|
|
No,
|
|
|
|
|
Yes,
|
|
|
|
|
};
|
2026-04-12 13:31:30 +02:00
|
|
|
static WebIDL::ExceptionOr<Vector<GC::Root<DOM::Node>>> parse_html_fragment(DOM::Element& context_element, StringView markup, AllowDeclarativeShadowRoots = AllowDeclarativeShadowRoots::No, ParserScriptingMode = ParserScriptingMode::Inert);
|
2025-09-10 23:06:59 +02:00
|
|
|
|
2024-06-25 10:49:54 +02:00
|
|
|
enum class SerializableShadowRoots {
|
|
|
|
|
No,
|
|
|
|
|
Yes,
|
|
|
|
|
};
|
2024-11-15 04:01:23 +13:00
|
|
|
static String serialize_html_fragment(DOM::Node const&, SerializableShadowRoots, Vector<GC::Root<DOM::ShadowRoot>> const&, DOM::FragmentSerializationMode = DOM::FragmentSerializationMode::Inner);
|
2020-06-25 23:42:08 +02:00
|
|
|
|
2020-05-24 00:14:23 +02:00
|
|
|
enum class InsertionMode {
|
|
|
|
|
#define __ENUMERATE_INSERTION_MODE(mode) mode,
|
|
|
|
|
ENUMERATE_INSERTION_MODES
|
|
|
|
|
#undef __ENUMERATE_INSERTION_MODE
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
InsertionMode insertion_mode() const { return m_insertion_mode; }
|
|
|
|
|
|
2023-11-04 10:19:21 +01:00
|
|
|
static bool is_special_tag(FlyString const& tag_name, Optional<FlyString> const& namespace_);
|
2020-05-29 22:06:05 +02:00
|
|
|
|
2022-02-19 15:58:21 +01:00
|
|
|
HTMLTokenizer& tokenizer() { return m_tokenizer; }
|
|
|
|
|
|
2022-09-20 21:08:14 +02:00
|
|
|
// https://html.spec.whatwg.org/multipage/parsing.html#abort-a-parser
|
|
|
|
|
void abort();
|
|
|
|
|
|
2022-02-19 15:58:21 +01:00
|
|
|
bool aborted() const { return m_aborted; }
|
2022-09-20 21:08:14 +02:00
|
|
|
bool stopped() const { return m_stop_parsing; }
|
2022-02-19 15:58:21 +01:00
|
|
|
|
|
|
|
|
size_t script_nesting_level() const { return m_script_nesting_level; }
|
|
|
|
|
|
2020-05-24 00:14:23 +02:00
|
|
|
private:
|
2026-04-12 13:31:30 +02:00
|
|
|
HTMLParser(DOM::Document&, ParserScriptingMode, StringView input, StringView encoding);
|
|
|
|
|
HTMLParser(DOM::Document&, ParserScriptingMode);
|
2022-02-21 21:54:21 +01:00
|
|
|
|
2022-10-17 10:46:11 +02:00
|
|
|
virtual void visit_edges(Cell::Visitor&) override;
|
2025-04-04 09:20:27 -06:00
|
|
|
virtual void initialize(JS::Realm&) override;
|
2022-10-17 10:46:11 +02:00
|
|
|
|
2022-04-01 20:58:27 +03:00
|
|
|
char const* insertion_mode_name() const;
|
2020-05-24 00:14:23 +02:00
|
|
|
|
2022-04-01 20:58:27 +03:00
|
|
|
DOM::QuirksMode which_quirks_mode(HTMLToken const&) const;
|
2020-07-18 21:17:17 +01:00
|
|
|
|
2020-05-24 00:14:23 +02:00
|
|
|
void handle_initial(HTMLToken&);
|
|
|
|
|
void handle_before_html(HTMLToken&);
|
|
|
|
|
void handle_before_head(HTMLToken&);
|
|
|
|
|
void handle_in_head(HTMLToken&);
|
|
|
|
|
void handle_in_head_noscript(HTMLToken&);
|
|
|
|
|
void handle_after_head(HTMLToken&);
|
|
|
|
|
void handle_in_body(HTMLToken&);
|
2020-05-24 00:49:22 +02:00
|
|
|
void handle_after_body(HTMLToken&);
|
|
|
|
|
void handle_after_after_body(HTMLToken&);
|
2020-05-24 00:14:23 +02:00
|
|
|
void handle_text(HTMLToken&);
|
2020-05-25 20:30:34 +02:00
|
|
|
void handle_in_table(HTMLToken&);
|
2020-05-28 00:27:46 +02:00
|
|
|
void handle_in_table_body(HTMLToken&);
|
|
|
|
|
void handle_in_row(HTMLToken&);
|
|
|
|
|
void handle_in_cell(HTMLToken&);
|
2020-05-30 17:57:41 +02:00
|
|
|
void handle_in_table_text(HTMLToken&);
|
2020-06-13 05:09:54 +01:00
|
|
|
void handle_in_caption(HTMLToken&);
|
2020-06-13 06:22:18 +01:00
|
|
|
void handle_in_column_group(HTMLToken&);
|
2020-06-21 06:58:03 +02:00
|
|
|
void handle_in_template(HTMLToken&);
|
|
|
|
|
void handle_in_frameset(HTMLToken&);
|
|
|
|
|
void handle_after_frameset(HTMLToken&);
|
|
|
|
|
void handle_after_after_frameset(HTMLToken&);
|
2020-05-24 00:14:23 +02:00
|
|
|
|
2020-05-28 18:55:18 +02:00
|
|
|
void stop_parsing() { m_stop_parsing = true; }
|
|
|
|
|
|
2023-10-01 20:07:44 +13:00
|
|
|
void generate_implied_end_tags(FlyString const& exception = {});
|
2020-08-19 22:30:33 +01:00
|
|
|
void generate_all_implied_end_tags_thoroughly();
|
2024-11-15 04:01:23 +13:00
|
|
|
GC::Ref<DOM::Element> create_element_for(HTMLToken const&, Optional<FlyString> const& namespace_, DOM::Node& intended_parent);
|
2020-06-21 17:00:55 +02:00
|
|
|
|
|
|
|
|
struct AdjustedInsertionLocation {
|
2024-11-15 04:01:23 +13:00
|
|
|
GC::Ptr<DOM::Node> parent;
|
|
|
|
|
GC::Ptr<DOM::Node> insert_before_sibling;
|
2020-06-21 17:00:55 +02:00
|
|
|
};
|
|
|
|
|
|
2024-11-15 04:01:23 +13:00
|
|
|
AdjustedInsertionLocation find_appropriate_place_for_inserting_node(GC::Ptr<DOM::Element> override_target = nullptr);
|
2020-06-21 17:00:55 +02:00
|
|
|
|
2024-11-15 04:01:23 +13:00
|
|
|
void insert_an_element_at_the_adjusted_insertion_location(GC::Ref<DOM::Element>);
|
2024-06-25 09:43:50 +02:00
|
|
|
|
2020-07-26 19:37:56 +02:00
|
|
|
DOM::Text* find_character_insertion_node();
|
2020-06-03 21:53:08 +02:00
|
|
|
void flush_character_insertions();
|
2024-06-25 09:43:50 +02:00
|
|
|
enum class OnlyAddToElementStack {
|
|
|
|
|
No,
|
|
|
|
|
Yes,
|
|
|
|
|
};
|
2024-11-15 04:01:23 +13:00
|
|
|
GC::Ref<DOM::Element> insert_foreign_element(HTMLToken const&, Optional<FlyString> const& namespace_, OnlyAddToElementStack);
|
|
|
|
|
GC::Ref<DOM::Element> insert_html_element(HTMLToken const&);
|
|
|
|
|
[[nodiscard]] GC::Ptr<DOM::Element> current_node();
|
|
|
|
|
[[nodiscard]] GC::Ptr<DOM::Element> adjusted_current_node();
|
|
|
|
|
[[nodiscard]] GC::Ptr<DOM::Element> node_before_current_node();
|
2020-05-24 19:51:50 +02:00
|
|
|
void insert_character(u32 data);
|
2020-05-24 20:29:01 +02:00
|
|
|
void insert_comment(HTMLToken&);
|
2020-05-24 19:51:50 +02:00
|
|
|
void reconstruct_the_active_formatting_elements();
|
2020-05-24 22:21:25 +02:00
|
|
|
void close_a_p_element();
|
2020-05-24 19:51:50 +02:00
|
|
|
void process_using_the_rules_for(InsertionMode, HTMLToken&);
|
2020-10-12 01:51:28 +01:00
|
|
|
void process_using_the_rules_for_foreign_content(HTMLToken&);
|
2020-05-24 20:36:43 +02:00
|
|
|
void parse_generic_raw_text_element(HTMLToken&);
|
2020-05-24 22:00:46 +02:00
|
|
|
void increment_script_nesting_level();
|
|
|
|
|
void decrement_script_nesting_level();
|
2020-07-21 19:03:05 +01:00
|
|
|
void reset_the_insertion_mode_appropriately();
|
2020-05-30 16:22:25 +02:00
|
|
|
|
2025-12-07 16:37:54 -08:00
|
|
|
void handle_element_popped(DOM::Element&);
|
|
|
|
|
|
2020-06-21 06:58:03 +02:00
|
|
|
void adjust_mathml_attributes(HTMLToken&);
|
2020-10-12 01:51:28 +01:00
|
|
|
void adjust_svg_tag_names(HTMLToken&);
|
2020-06-21 06:58:03 +02:00
|
|
|
void adjust_svg_attributes(HTMLToken&);
|
2023-11-04 11:26:44 +13:00
|
|
|
static void adjust_foreign_attributes(HTMLToken&);
|
2020-06-21 06:58:03 +02:00
|
|
|
|
2020-05-30 16:22:25 +02:00
|
|
|
enum AdoptionAgencyAlgorithmOutcome {
|
|
|
|
|
DoNothing,
|
|
|
|
|
RunAnyOtherEndTagSteps,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
AdoptionAgencyAlgorithmOutcome run_the_adoption_agency_algorithm(HTMLToken&);
|
2020-05-28 00:27:46 +02:00
|
|
|
void clear_the_stack_back_to_a_table_context();
|
|
|
|
|
void clear_the_stack_back_to_a_table_body_context();
|
|
|
|
|
void clear_the_stack_back_to_a_table_row_context();
|
2020-05-28 11:45:40 +02:00
|
|
|
void close_the_cell();
|
2020-05-24 00:14:23 +02:00
|
|
|
|
|
|
|
|
InsertionMode m_insertion_mode { InsertionMode::Initial };
|
2020-05-24 20:24:43 +02:00
|
|
|
InsertionMode m_original_insertion_mode { InsertionMode::Initial };
|
2020-05-24 19:51:50 +02:00
|
|
|
|
2020-05-24 19:24:36 +02:00
|
|
|
StackOfOpenElements m_stack_of_open_elements;
|
2020-06-21 06:58:03 +02:00
|
|
|
Vector<InsertionMode> m_stack_of_template_insertion_modes;
|
2020-05-27 23:22:42 +02:00
|
|
|
ListOfActiveFormattingElements m_list_of_active_formatting_elements;
|
2020-05-24 19:51:50 +02:00
|
|
|
|
2020-05-24 00:14:23 +02:00
|
|
|
HTMLTokenizer m_tokenizer;
|
|
|
|
|
|
2025-02-19 16:54:28 +01:00
|
|
|
bool m_next_line_feed_can_be_ignored { false };
|
|
|
|
|
|
2020-05-24 00:14:23 +02:00
|
|
|
bool m_foster_parenting { false };
|
2020-05-24 00:49:22 +02:00
|
|
|
bool m_frameset_ok { true };
|
|
|
|
|
bool m_parsing_fragment { false };
|
2022-09-23 20:43:17 +01:00
|
|
|
|
2026-04-12 13:31:30 +02:00
|
|
|
// https://html.spec.whatwg.org/multipage/parsing.html#scripting-mode
|
|
|
|
|
ParserScriptingMode m_scripting_mode {};
|
2022-09-23 20:43:17 +01:00
|
|
|
|
2020-05-24 22:00:46 +02:00
|
|
|
bool m_invoked_via_document_write { false };
|
2020-05-27 23:01:04 +02:00
|
|
|
bool m_aborted { false };
|
2020-05-24 22:00:46 +02:00
|
|
|
bool m_parser_pause_flag { false };
|
2020-05-28 18:55:18 +02:00
|
|
|
bool m_stop_parsing { false };
|
2020-05-24 22:00:46 +02:00
|
|
|
size_t m_script_nesting_level { 0 };
|
2020-05-24 00:14:23 +02:00
|
|
|
|
2022-08-28 13:42:07 +02:00
|
|
|
JS::Realm& realm();
|
|
|
|
|
|
2024-11-15 04:01:23 +13:00
|
|
|
GC::Ptr<DOM::Document> m_document;
|
|
|
|
|
GC::Ptr<HTMLHeadElement> m_head_element;
|
|
|
|
|
GC::Ptr<HTMLFormElement> m_form_element;
|
|
|
|
|
GC::Ptr<DOM::Element> m_context_element;
|
2020-05-30 17:57:41 +02:00
|
|
|
|
|
|
|
|
Vector<HTMLToken> m_pending_table_character_tokens;
|
2020-06-03 21:53:08 +02:00
|
|
|
|
2024-11-15 04:01:23 +13:00
|
|
|
GC::Ptr<DOM::Text> m_character_insertion_node;
|
2025-07-24 12:05:52 -04:00
|
|
|
StringBuilder m_character_insertion_builder { StringBuilder::Mode::UTF16 };
|
2026-02-17 14:23:39 +01:00
|
|
|
};
|
2020-05-24 00:14:23 +02:00
|
|
|
|
LibWeb: Replace spin_until in HTMLParser::the_end() with state machine
HTMLParser::the_end() had three spin_until calls that blocked the event
loop: step 5 (deferred scripts), step 7 (ASAP scripts), and step 8
(load event delay). This replaces them with an HTMLParserEndState state
machine that progresses asynchronously via callbacks.
The state machine has three phases matching the three spin_until calls:
- WaitingForDeferredScripts: loops executing ready deferred scripts
- WaitingForASAPScripts: waits for ASAP script lists to empty
- WaitingForLoadEventDelay: waits for nothing to delay the load event
Notification triggers re-evaluate the state machine when conditions
change: HTMLScriptElement::mark_as_ready, stylesheet unblocking in
StyleElementBase/HTMLLinkElement, did_stop_being_active_document, and
DocumentLoadEventDelayer decrements. NavigableContainer state changes
(session history readiness, content navigable cleared, lazy load flag)
also trigger re-evaluation of the load event delay check.
Key design decisions and why:
1. Microtask checkpoint in schedule_progress_check(): The old spin_until
called perform_a_microtask_checkpoint() before checking conditions.
This is critical because HTMLImageElement::update_the_image_data step
8 queues a microtask that creates the DocumentLoadEventDelayer.
Without the checkpoint, check_progress() would see zero delayers and
complete before images start delaying the load event.
2. deferred_invoke in schedule_progress_check():
I tried Core::Timer (0ms), queue_global_task, and synchronous calls.
Timers caused non-deterministic ordering with the HTML event loop's
task processing timer, leading to image layout tests failing (wrong
subtest pass/fail patterns). Synchronous calls fired too early during
image load processing before dimensions were set, causing 0-height
images in layout tests. queue_global_task had task ordering issues
with the session history traversal queue. deferred_invoke runs after
the current callback returns but within the same event loop pump,
giving the right balance.
3. Navigation load event guard (m_navigation_load_event_guard): During
cross-document navigation, finalize_a_cross_document_navigation step
2 calls set_delaying_load_events(false) before the session history
traversal activates the new document. This creates a transient state
where the parent's load event delay check sees the about:blank (which
has ready_for_post_load_tasks=true) as the active document and
completes prematurely.
2026-03-28 09:39:51 +01:00
|
|
|
class HTMLParserEndState final : public JS::Cell {
|
|
|
|
|
GC_CELL(HTMLParserEndState, JS::Cell);
|
|
|
|
|
GC_DECLARE_ALLOCATOR(HTMLParserEndState);
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
static GC::Ref<HTMLParserEndState> create(GC::Ref<DOM::Document>, GC::Ptr<HTMLParser>);
|
|
|
|
|
|
|
|
|
|
void schedule_progress_check();
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
enum class Phase {
|
|
|
|
|
WaitingForDeferredScripts,
|
|
|
|
|
WaitingForASAPScripts,
|
|
|
|
|
WaitingForLoadEventDelay,
|
|
|
|
|
Completed,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
HTMLParserEndState(GC::Ref<DOM::Document>, GC::Ptr<HTMLParser>);
|
|
|
|
|
|
|
|
|
|
virtual void visit_edges(Cell::Visitor&) override;
|
|
|
|
|
|
|
|
|
|
void check_progress();
|
|
|
|
|
void advance_to_asap_scripts_phase();
|
|
|
|
|
void complete();
|
|
|
|
|
|
|
|
|
|
Phase m_phase { Phase::WaitingForDeferredScripts };
|
|
|
|
|
bool m_check_pending { false };
|
|
|
|
|
|
|
|
|
|
GC::Ref<DOM::Document> m_document;
|
|
|
|
|
GC::Ptr<HTMLParser> m_parser;
|
|
|
|
|
GC::Ref<Platform::Timer> m_timeout;
|
|
|
|
|
};
|
|
|
|
|
|
2025-08-08 10:11:51 +01:00
|
|
|
RefPtr<CSS::StyleValue const> parse_dimension_value(StringView);
|
|
|
|
|
RefPtr<CSS::StyleValue const> parse_nonzero_dimension_value(StringView);
|
2024-01-16 19:04:45 +01:00
|
|
|
Optional<Color> parse_legacy_color_value(StringView);
|
2022-03-26 14:29:52 +01:00
|
|
|
|
2020-05-24 00:14:23 +02:00
|
|
|
}
|