Skip to content

Commit e7af6af

Browse files
committed
LibWeb: Implement more of HTMLParser::the_end() and bring closer to spec
1 parent c772134 commit e7af6af

File tree

4 files changed

+75
-12
lines changed

4 files changed

+75
-12
lines changed

Userland/Libraries/LibWeb/DOM/Document.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ class Document
191191

192192
void add_script_to_execute_when_parsing_has_finished(Badge<HTML::HTMLScriptElement>, HTML::HTMLScriptElement&);
193193
NonnullRefPtrVector<HTML::HTMLScriptElement> take_scripts_to_execute_when_parsing_has_finished(Badge<HTML::HTMLParser>);
194+
NonnullRefPtrVector<HTML::HTMLScriptElement>& scripts_to_execute_when_parsing_has_finished() { return m_scripts_to_execute_when_parsing_has_finished; }
194195

195196
void add_script_to_execute_as_soon_as_possible(Badge<HTML::HTMLScriptElement>, HTML::HTMLScriptElement&);
196197
NonnullRefPtrVector<HTML::HTMLScriptElement> take_scripts_to_execute_as_soon_as_possible(Badge<HTML::HTMLParser>);

Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,4 +178,11 @@ void EventLoop::process()
178178
schedule();
179179
}
180180

181+
// https://html.spec.whatwg.org/multipage/webappapis.html#queue-a-global-task
182+
void queue_global_task(HTML::Task::Source source, DOM::Document& document, Function<void()> steps)
183+
{
184+
// FIXME: This should take a global object as input and find the relevant document for it.
185+
main_thread_event_loop().task_queue().add(HTML::Task::create(source, &document, move(steps)));
186+
}
187+
181188
}

Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,5 +58,6 @@ class EventLoop {
5858
};
5959

6060
EventLoop& main_thread_event_loop();
61+
void queue_global_task(HTML::Task::Source, DOM::Document&, Function<void()> steps);
6162

6263
}

Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp

Lines changed: 66 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -194,31 +194,85 @@ void HTMLParser::the_end()
194194
while (!m_stack_of_open_elements.is_empty())
195195
m_stack_of_open_elements.pop();
196196

197-
auto scripts_to_execute_when_parsing_has_finished = m_document->take_scripts_to_execute_when_parsing_has_finished({});
198-
199-
for (auto& script : scripts_to_execute_when_parsing_has_finished) {
197+
// 5. While the list of scripts that will execute when the document has finished parsing is not empty:
198+
while (!m_document->scripts_to_execute_when_parsing_has_finished().is_empty()) {
199+
// 1. Spin the event loop until the first script in the list of scripts that will execute when the document has finished parsing
200+
// has its "ready to be parser-executed" flag set and the parser's Document has no style sheet that is blocking scripts.
200201
main_thread_event_loop().spin_until([&] {
201-
return script.is_ready_to_be_parser_executed() && !document().has_a_style_sheet_that_is_blocking_scripts();
202+
return m_document->scripts_to_execute_when_parsing_has_finished().first().is_ready_to_be_parser_executed()
203+
&& !m_document->has_a_style_sheet_that_is_blocking_scripts();
202204
});
203-
script.execute_script();
205+
206+
// 2. Execute the first script in the list of scripts that will execute when the document has finished parsing.
207+
m_document->scripts_to_execute_when_parsing_has_finished().first().execute_script();
208+
209+
// 3. Remove the first script element from the list of scripts that will execute when the document has finished parsing (i.e. shift out the first entry in the list).
210+
m_document->scripts_to_execute_when_parsing_has_finished().take_first();
204211
}
205212

206-
auto content_loaded_event = DOM::Event::create(HTML::EventNames::DOMContentLoaded);
207-
content_loaded_event->set_bubbles(true);
208-
m_document->dispatch_event(content_loaded_event);
213+
// 6. Queue a global task on the DOM manipulation task source given the Document's relevant global object to run the following substeps:
214+
queue_global_task(HTML::Task::Source::DOMManipulation, *m_document, [document = m_document]() mutable {
215+
// FIXME: 1. Set the Document's load timing info's DOM content loaded event start time to the current high resolution time given the Document's relevant global object.
216+
217+
// 2. Fire an event named DOMContentLoaded at the Document object, with its bubbles attribute initialized to true.
218+
auto content_loaded_event = DOM::Event::create(HTML::EventNames::DOMContentLoaded);
219+
content_loaded_event->set_bubbles(true);
220+
document->dispatch_event(content_loaded_event);
221+
222+
// FIXME: 3. Set the Document's load timing info's DOM content loaded event end time to the current high resolution time given the Document's relevant global object.
223+
224+
// FIXME: 4. Enable the client message queue of the ServiceWorkerContainer object whose associated service worker client is the Document object's relevant settings object.
225+
226+
// FIXME: 5. Invoke WebDriver BiDi DOM content loaded with the Document's browsing context, and a new WebDriver BiDi navigation status whose id is the Document object's navigation id, status is "pending", and url is the Document object's URL.
227+
});
209228

210229
// 7. Spin the event loop until the set of scripts that will execute as soon as possible and the list of scripts that will execute in order as soon as possible are empty.
211230
main_thread_event_loop().spin_until([&] {
212231
return m_document->scripts_to_execute_as_soon_as_possible().is_empty();
213232
});
214233

215-
// FIXME: Spin the event loop until there is nothing that delays the load event in the Document.
234+
// FIXME: 8. Spin the event loop until there is nothing that delays the load event in the Document.
235+
236+
// 9. Queue a global task on the DOM manipulation task source given the Document's relevant global object to run the following steps:
237+
queue_global_task(HTML::Task::Source::DOMManipulation, *m_document, [document = m_document]() mutable {
238+
// 1. Update the current document readiness to "complete".
239+
document->set_ready_state("complete");
240+
241+
// 2. If the Document object's browsing context is null, then abort these steps.
242+
if (!document->browsing_context())
243+
return;
244+
245+
// FIXME: 3. Let window be the Document's relevant global object.
246+
247+
// FIXME: 4. Set the Document's load timing info's load event start time to the current high resolution time given window.
248+
249+
// 5. Fire an event named load at window, with legacy target override flag set.
250+
// FIXME: The legacy target override flag is currently set by a virtual override of dispatch_event()
251+
// We should reorganize this so that the flag appears explicitly here instead.
252+
document->window().dispatch_event(DOM::Event::create(HTML::EventNames::load));
253+
254+
// FIXME: 6. Invoke WebDriver BiDi load complete with the Document's browsing context, and a new WebDriver BiDi navigation status whose id is the Document object's navigation id, status is "complete", and url is the Document object's URL.
255+
256+
// FIXME: 7. Set the Document object's navigation id to null.
257+
258+
// FIXME: 8. Set the Document's load timing info's load event end time to the current high resolution time given window.
259+
260+
// FIXME: 9. Assert: Document's page showing is false.
261+
262+
// FIXME: 10. Set the Document's page showing flag to true.
263+
264+
// FIXME: 11. Fire a page transition event named pageshow at window with false.
265+
266+
// 12. Completely finish loading the Document.
267+
document->completely_finish_loading();
268+
269+
// FIXME: 13. Queue the navigation timing entry for the Document.
270+
});
216271

217-
m_document->set_ready_state("complete");
218-
m_document->window().dispatch_event(DOM::Event::create(HTML::EventNames::load));
272+
// FIXME: 10. If the Document's print when loaded flag is set, then run the printing steps.
219273

274+
// 11. The Document is now ready for post-load tasks.
220275
m_document->set_ready_for_post_load_tasks(true);
221-
m_document->completely_finish_loading();
222276
}
223277

224278
void HTMLParser::process_using_the_rules_for(InsertionMode mode, HTMLToken& token)

0 commit comments

Comments
 (0)