mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 06:38:10 +00:00
LibWeb: Flesh out prepare_script and execute_script
This fills in a bunch of the FIXMEs that was in prepare_script. execute_script is almost finished, it's just missing the module side. As an aside, let's not assert when inserting a script element with innerHTML.
This commit is contained in:
parent
dbbc378fb2
commit
3f5532d43e
8 changed files with 188 additions and 40 deletions
|
@ -65,6 +65,7 @@
|
||||||
#cmakedefine01 HEAP_DEBUG
|
#cmakedefine01 HEAP_DEBUG
|
||||||
#cmakedefine01 HEX_DEBUG
|
#cmakedefine01 HEX_DEBUG
|
||||||
#cmakedefine01 HIGHLIGHT_FOCUSED_FRAME_DEBUG
|
#cmakedefine01 HIGHLIGHT_FOCUSED_FRAME_DEBUG
|
||||||
|
#cmakedefine01 HTML_SCRIPT_DEBUG
|
||||||
#cmakedefine01 HTTPSJOB_DEBUG
|
#cmakedefine01 HTTPSJOB_DEBUG
|
||||||
#cmakedefine01 HUNKS_DEBUG
|
#cmakedefine01 HUNKS_DEBUG
|
||||||
#cmakedefine01 ICO_DEBUG
|
#cmakedefine01 ICO_DEBUG
|
||||||
|
|
|
@ -126,6 +126,7 @@ set(GLOBAL_DTORS_DEBUG ON)
|
||||||
set(GMENU_DEBUG ON)
|
set(GMENU_DEBUG ON)
|
||||||
set(HEAP_DEBUG ON)
|
set(HEAP_DEBUG ON)
|
||||||
set(HEX_DEBUG ON)
|
set(HEX_DEBUG ON)
|
||||||
|
set(HTML_SCRIPT_DEBUG ON)
|
||||||
set(HTTPSJOB_DEBUG ON)
|
set(HTTPSJOB_DEBUG ON)
|
||||||
set(ICMP_DEBUG ON)
|
set(ICMP_DEBUG ON)
|
||||||
set(ICO_DEBUG ON)
|
set(ICO_DEBUG ON)
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include <LibWeb/DOM/DOMImplementation.h>
|
#include <LibWeb/DOM/DOMImplementation.h>
|
||||||
#include <LibWeb/DOM/NonElementParentNode.h>
|
#include <LibWeb/DOM/NonElementParentNode.h>
|
||||||
#include <LibWeb/DOM/ParentNode.h>
|
#include <LibWeb/DOM/ParentNode.h>
|
||||||
|
#include <LibWeb/HTML/HTMLScriptElement.h>
|
||||||
|
|
||||||
namespace Web::DOM {
|
namespace Web::DOM {
|
||||||
|
|
||||||
|
@ -220,6 +221,13 @@ public:
|
||||||
|
|
||||||
const NonnullRefPtr<DOMImplementation> implementation() const { return m_implementation; }
|
const NonnullRefPtr<DOMImplementation> implementation() const { return m_implementation; }
|
||||||
|
|
||||||
|
RefPtr<HTML::HTMLScriptElement> current_script() const { return m_current_script; }
|
||||||
|
void set_current_script(Badge<HTML::HTMLScriptElement>, RefPtr<HTML::HTMLScriptElement> script) { m_current_script = script; }
|
||||||
|
|
||||||
|
u32 ignore_destructive_writes_counter() const { return m_ignore_destructive_writes_counter; }
|
||||||
|
void increment_ignore_destructive_writes_counter() { m_ignore_destructive_writes_counter++; }
|
||||||
|
void decrement_ignore_destructive_writes_counter() { m_ignore_destructive_writes_counter--; }
|
||||||
|
|
||||||
virtual EventTarget* get_parent(const Event&) override;
|
virtual EventTarget* get_parent(const Event&) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -289,8 +297,11 @@ private:
|
||||||
bool m_ready_for_post_load_tasks { false };
|
bool m_ready_for_post_load_tasks { false };
|
||||||
|
|
||||||
NonnullRefPtr<DOMImplementation> m_implementation;
|
NonnullRefPtr<DOMImplementation> m_implementation;
|
||||||
|
RefPtr<HTML::HTMLScriptElement> m_current_script;
|
||||||
|
|
||||||
bool m_should_invalidate_styles_on_attribute_changes { true };
|
bool m_should_invalidate_styles_on_attribute_changes { true };
|
||||||
|
|
||||||
|
u32 m_ignore_destructive_writes_counter { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ interface Document : Node {
|
||||||
readonly attribute Element? documentElement;
|
readonly attribute Element? documentElement;
|
||||||
attribute HTMLElement? body;
|
attribute HTMLElement? body;
|
||||||
readonly attribute HTMLHeadElement? head;
|
readonly attribute HTMLHeadElement? head;
|
||||||
|
readonly attribute HTMLScriptElement? currentScript;
|
||||||
|
|
||||||
readonly attribute DOMString readyState;
|
readonly attribute DOMString readyState;
|
||||||
|
|
||||||
|
|
|
@ -98,6 +98,7 @@ namespace AttributeNames {
|
||||||
__ENUMERATE_HTML_ATTRIBUTE(ismap) \
|
__ENUMERATE_HTML_ATTRIBUTE(ismap) \
|
||||||
__ENUMERATE_HTML_ATTRIBUTE(label) \
|
__ENUMERATE_HTML_ATTRIBUTE(label) \
|
||||||
__ENUMERATE_HTML_ATTRIBUTE(lang) \
|
__ENUMERATE_HTML_ATTRIBUTE(lang) \
|
||||||
|
__ENUMERATE_HTML_ATTRIBUTE(language) \
|
||||||
__ENUMERATE_HTML_ATTRIBUTE(link) \
|
__ENUMERATE_HTML_ATTRIBUTE(link) \
|
||||||
__ENUMERATE_HTML_ATTRIBUTE(longdesc) \
|
__ENUMERATE_HTML_ATTRIBUTE(longdesc) \
|
||||||
__ENUMERATE_HTML_ATTRIBUTE(loop) \
|
__ENUMERATE_HTML_ATTRIBUTE(loop) \
|
||||||
|
|
|
@ -24,10 +24,13 @@
|
||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <AK/Debug.h>
|
||||||
#include <AK/StringBuilder.h>
|
#include <AK/StringBuilder.h>
|
||||||
#include <LibJS/Parser.h>
|
#include <LibJS/Parser.h>
|
||||||
|
#include <LibTextCodec/Decoder.h>
|
||||||
#include <LibWeb/DOM/Document.h>
|
#include <LibWeb/DOM/Document.h>
|
||||||
#include <LibWeb/DOM/Event.h>
|
#include <LibWeb/DOM/Event.h>
|
||||||
|
#include <LibWeb/DOM/ShadowRoot.h>
|
||||||
#include <LibWeb/DOM/Text.h>
|
#include <LibWeb/DOM/Text.h>
|
||||||
#include <LibWeb/HTML/EventNames.h>
|
#include <LibWeb/HTML/EventNames.h>
|
||||||
#include <LibWeb/HTML/HTMLScriptElement.h>
|
#include <LibWeb/HTML/HTMLScriptElement.h>
|
||||||
|
@ -56,16 +59,68 @@ void HTMLScriptElement::set_non_blocking(Badge<HTMLDocumentParser>, bool non_blo
|
||||||
|
|
||||||
void HTMLScriptElement::execute_script()
|
void HTMLScriptElement::execute_script()
|
||||||
{
|
{
|
||||||
document().run_javascript(m_script_source);
|
if (m_preparation_time_document.ptr() != &document()) {
|
||||||
|
dbgln("HTMLScriptElement: Refusing to run script because the preparation time document is not the same as the node document.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (has_attribute(HTML::AttributeNames::src))
|
if (m_script_source.is_null()) {
|
||||||
dispatch_event(DOM::Event::create(EventNames::load));
|
dbgln("HTMLScriptElement: Refusing to run script because the script source is null.");
|
||||||
|
dispatch_event(DOM::Event::create(HTML::EventNames::error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool incremented_destructive_writes_counter = false;
|
||||||
|
|
||||||
|
if (m_from_an_external_file || m_script_type == ScriptType::Module) {
|
||||||
|
document().increment_ignore_destructive_writes_counter();
|
||||||
|
incremented_destructive_writes_counter = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_script_type == ScriptType::Classic) {
|
||||||
|
auto old_current_script = document().current_script();
|
||||||
|
if (!is<DOM::ShadowRoot>(root()))
|
||||||
|
document().set_current_script({}, this);
|
||||||
|
else
|
||||||
|
document().set_current_script({}, nullptr);
|
||||||
|
|
||||||
|
if (m_from_an_external_file)
|
||||||
|
dbgln<HTML_SCRIPT_DEBUG>("HTMLScriptElement: Running script {}", attribute(HTML::AttributeNames::src));
|
||||||
|
else
|
||||||
|
dbgln<HTML_SCRIPT_DEBUG>("HTMLScriptElement: Running inline script");
|
||||||
|
|
||||||
|
document().run_javascript(m_script_source);
|
||||||
|
|
||||||
|
document().set_current_script({}, old_current_script);
|
||||||
|
} else {
|
||||||
|
ASSERT(!document().current_script());
|
||||||
|
TODO();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (incremented_destructive_writes_counter)
|
||||||
|
document().decrement_ignore_destructive_writes_counter();
|
||||||
|
|
||||||
|
if (m_from_an_external_file)
|
||||||
|
dispatch_event(DOM::Event::create(HTML::EventNames::load));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://mimesniff.spec.whatwg.org/#javascript-mime-type-essence-match
|
||||||
|
static bool is_javascript_mime_type_essence_match(const String& mime_type)
|
||||||
|
{
|
||||||
|
// FIXME: This operates on the whole mime type, instead of just the essence. https://mimesniff.spec.whatwg.org/#mime-type-essence
|
||||||
|
// It'd probably be best to make a helper class for mime types, since there is a whole spec about mime types.
|
||||||
|
auto lowercase_mime_type = mime_type.to_lowercase();
|
||||||
|
return lowercase_mime_type.is_one_of("application/ecmascript", "application/javascript", "application/x-ecmascript", "application/x-javascript", "text/ecmascript", "text/javascript", "text/javascript1.0", "text/javascript1.1", "text/javascript1.2", "text/javascript1.3", "text/javascript1.4", "text/javascript1.5", "text/jscript", "text/livescript", "text/x-ecmascript", "text/x-javascript");
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/scripting.html#prepare-a-script
|
||||||
void HTMLScriptElement::prepare_script(Badge<HTMLDocumentParser>)
|
void HTMLScriptElement::prepare_script(Badge<HTMLDocumentParser>)
|
||||||
{
|
{
|
||||||
if (m_already_started)
|
if (m_already_started) {
|
||||||
|
dbgln("HTMLScriptElement: Refusing to run script because it has already started.");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
RefPtr<DOM::Document> parser_document = m_parser_document.ptr();
|
RefPtr<DOM::Document> parser_document = m_parser_document.ptr();
|
||||||
m_parser_document = nullptr;
|
m_parser_document = nullptr;
|
||||||
|
|
||||||
|
@ -74,13 +129,37 @@ void HTMLScriptElement::prepare_script(Badge<HTMLDocumentParser>)
|
||||||
}
|
}
|
||||||
|
|
||||||
auto source_text = child_text_content();
|
auto source_text = child_text_content();
|
||||||
if (!has_attribute(HTML::AttributeNames::src) && source_text.is_empty())
|
if (!has_attribute(HTML::AttributeNames::src) && source_text.is_empty()) {
|
||||||
|
dbgln("HTMLScriptElement: Refusing to run empty script.");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!is_connected())
|
if (!is_connected()) {
|
||||||
|
dbgln("HTMLScriptElement: Refusing to run script because the element is not connected.");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: Check the "type" and "language" attributes
|
String script_block_type;
|
||||||
|
bool has_type = has_attribute(HTML::AttributeNames::type);
|
||||||
|
bool has_language = has_attribute(HTML::AttributeNames::language);
|
||||||
|
if ((has_type && attribute(HTML::AttributeNames::type).is_empty())
|
||||||
|
|| (!has_type && has_language && attribute(HTML::AttributeNames::language).is_empty())
|
||||||
|
|| (!has_type && !has_language)) {
|
||||||
|
script_block_type = "text/javascript";
|
||||||
|
} else if (has_type) {
|
||||||
|
script_block_type = attribute(HTML::AttributeNames::type).trim_whitespace();
|
||||||
|
} else if (!attribute(HTML::AttributeNames::language).is_empty()) {
|
||||||
|
script_block_type = String::formatted("text/{}", attribute(HTML::AttributeNames::language));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_javascript_mime_type_essence_match(script_block_type)) {
|
||||||
|
m_script_type = ScriptType::Classic;
|
||||||
|
} else if (script_block_type.equals_ignoring_case("module")) {
|
||||||
|
m_script_type = ScriptType::Module;
|
||||||
|
} else {
|
||||||
|
dbgln("HTMLScriptElement: Refusing to run script because the type '{}' is not recognized.", script_block_type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (parser_document) {
|
if (parser_document) {
|
||||||
m_parser_document = *parser_document;
|
m_parser_document = *parser_document;
|
||||||
|
@ -91,13 +170,34 @@ void HTMLScriptElement::prepare_script(Badge<HTMLDocumentParser>)
|
||||||
m_preparation_time_document = document();
|
m_preparation_time_document = document();
|
||||||
|
|
||||||
if (parser_document && parser_document.ptr() != m_preparation_time_document.ptr()) {
|
if (parser_document && parser_document.ptr() != m_preparation_time_document.ptr()) {
|
||||||
|
dbgln("HTMLScriptElement: Refusing to run script because the parser document is not the same as the preparation time document.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Check if scripting is disabled, if so return
|
// FIXME: Check if scripting is disabled, if so return
|
||||||
// FIXME: Check the "nomodule" content attribute
|
|
||||||
|
if (m_script_type == ScriptType::Classic && has_attribute(HTML::AttributeNames::nomodule)) {
|
||||||
|
dbgln("HTMLScriptElement: Refusing to run classic script because it has the nomodule attribute.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: Check CSP
|
// FIXME: Check CSP
|
||||||
// FIXME: Check "event" and "for" attributes
|
|
||||||
|
if (m_script_type == ScriptType::Classic && has_attribute(HTML::AttributeNames::event) && has_attribute(HTML::AttributeNames::for_)) {
|
||||||
|
auto for_ = attribute(HTML::AttributeNames::for_).trim_whitespace();
|
||||||
|
auto event = attribute(HTML::AttributeNames::event).trim_whitespace();
|
||||||
|
|
||||||
|
if (!for_.equals_ignoring_case("window")) {
|
||||||
|
dbgln("HTMLScriptElement: Refusing to run classic script because the provided 'for' attribute is not equal to 'window'");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!event.equals_ignoring_case("onload") && !event.equals_ignoring_case("onload()")) {
|
||||||
|
dbgln("HTMLScriptElement: Refusing to run classic script because the provided 'event' attribute is not equal to 'onload' or 'onload()'");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: Check "charset" attribute
|
// FIXME: Check "charset" attribute
|
||||||
// FIXME: Check CORS
|
// FIXME: Check CORS
|
||||||
// FIXME: Module script credentials mode
|
// FIXME: Module script credentials mode
|
||||||
|
@ -112,60 +212,83 @@ void HTMLScriptElement::prepare_script(Badge<HTMLDocumentParser>)
|
||||||
if (has_attribute(HTML::AttributeNames::src)) {
|
if (has_attribute(HTML::AttributeNames::src)) {
|
||||||
auto src = attribute(HTML::AttributeNames::src);
|
auto src = attribute(HTML::AttributeNames::src);
|
||||||
if (src.is_empty()) {
|
if (src.is_empty()) {
|
||||||
// FIXME: Fire an "error" event at the element and return
|
dbgln("HTMLScriptElement: Refusing to run script because the src attribute is empty.");
|
||||||
ASSERT_NOT_REACHED();
|
// FIXME: Queue a task to do this.
|
||||||
|
dispatch_event(DOM::Event::create(HTML::EventNames::error));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
m_from_an_external_file = true;
|
m_from_an_external_file = true;
|
||||||
|
|
||||||
auto url = document().complete_url(src);
|
auto url = document().complete_url(src);
|
||||||
if (!url.is_valid()) {
|
if (!url.is_valid()) {
|
||||||
// FIXME: Fire an "error" event at the element and return
|
dbgln("HTMLScriptElement: Refusing to run script because the src URL '{}' is invalid.", url);
|
||||||
ASSERT_NOT_REACHED();
|
// FIXME: Queue a task to do this.
|
||||||
|
dispatch_event(DOM::Event::create(HTML::EventNames::error));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Check classic vs. module script type
|
if (m_script_type == ScriptType::Classic) {
|
||||||
|
// FIXME: This load should be made asynchronous and the parser should spin an event loop etc.
|
||||||
// FIXME: This load should be made asynchronous and the parser should spin an event loop etc.
|
ResourceLoader::the().load_sync(
|
||||||
ResourceLoader::the().load_sync(
|
url,
|
||||||
url,
|
[this, url](auto data, auto&) {
|
||||||
[this, url](auto data, auto&) {
|
if (data.is_null()) {
|
||||||
if (data.is_null()) {
|
dbgln("HTMLScriptElement: Failed to load {}", url);
|
||||||
dbgln("HTMLScriptElement: Failed to load {}", url);
|
return;
|
||||||
return;
|
}
|
||||||
}
|
m_script_source = String::copy(data);
|
||||||
m_script_source = String::copy(data);
|
script_became_ready();
|
||||||
script_became_ready();
|
},
|
||||||
},
|
[this](auto&) {
|
||||||
[this](auto&) {
|
m_failed_to_load = true;
|
||||||
m_failed_to_load = true;
|
});
|
||||||
});
|
} else {
|
||||||
|
TODO();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// FIXME: Check classic vs. module script type
|
if (m_script_type == ScriptType::Classic) {
|
||||||
m_script_source = source_text;
|
m_script_source = source_text;
|
||||||
script_became_ready();
|
script_became_ready();
|
||||||
|
} else {
|
||||||
|
TODO();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Check classic vs. module
|
if ((m_script_type == ScriptType::Classic && has_attribute(HTML::AttributeNames::src) && has_attribute(HTML::AttributeNames::defer) && m_parser_inserted && !has_attribute(HTML::AttributeNames::async))
|
||||||
if (has_attribute(HTML::AttributeNames::src) && has_attribute(HTML::AttributeNames::defer) && m_parser_inserted && !has_attribute(HTML::AttributeNames::async)) {
|
|| (m_script_type == ScriptType::Module && m_parser_inserted && !has_attribute(HTML::AttributeNames::async))) {
|
||||||
document().add_script_to_execute_when_parsing_has_finished({}, *this);
|
document().add_script_to_execute_when_parsing_has_finished({}, *this);
|
||||||
|
when_the_script_is_ready([this] {
|
||||||
|
m_ready_to_be_parser_executed = true;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (has_attribute(HTML::AttributeNames::src) && m_parser_inserted && !has_attribute(HTML::AttributeNames::async)) {
|
else if (m_script_type == ScriptType::Classic && has_attribute(HTML::AttributeNames::src) && m_parser_inserted && !has_attribute(HTML::AttributeNames::async)) {
|
||||||
|
|
||||||
document().set_pending_parsing_blocking_script({}, this);
|
document().set_pending_parsing_blocking_script({}, this);
|
||||||
when_the_script_is_ready([this] {
|
when_the_script_is_ready([this] {
|
||||||
m_ready_to_be_parser_executed = true;
|
m_ready_to_be_parser_executed = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (has_attribute(HTML::AttributeNames::src) && !has_attribute(HTML::AttributeNames::async) && !m_non_blocking) {
|
else if ((m_script_type == ScriptType::Classic && has_attribute(HTML::AttributeNames::src) && !has_attribute(HTML::AttributeNames::async) && !m_non_blocking)
|
||||||
ASSERT_NOT_REACHED();
|
|| (m_script_type == ScriptType::Module && !has_attribute(HTML::AttributeNames::async) && !m_non_blocking)) {
|
||||||
|
TODO();
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (has_attribute(HTML::AttributeNames::src)) {
|
else if ((m_script_type == ScriptType::Classic && has_attribute(HTML::AttributeNames::src)) || m_script_type == ScriptType::Module) {
|
||||||
|
// FIXME: This should add to a set, not a list.
|
||||||
m_preparation_time_document->add_script_to_execute_as_soon_as_possible({}, *this);
|
m_preparation_time_document->add_script_to_execute_as_soon_as_possible({}, *this);
|
||||||
|
// FIXME: When the script is ready, execute the script block and then remove the element
|
||||||
|
// from the set of scripts that will execute as soon as possible.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: If the element does not have a src attribute, and the element is "parser-inserted",
|
||||||
|
// and either the parser that created the script is an XML parser or it's an HTML parser
|
||||||
|
// whose script nesting level is not greater than one, and the element's parser document
|
||||||
|
// has a style sheet that is blocking scripts:
|
||||||
|
// The element is the pending parsing-blocking script of its parser document.
|
||||||
|
// (There can only be one such script per Document at a time.)
|
||||||
|
// Set the element's "ready to be parser-executed" flag. The parser will handle executing the script.
|
||||||
|
|
||||||
else {
|
else {
|
||||||
// Immediately execute the script block, even if other scripts are already executing.
|
// Immediately execute the script block, even if other scripts are already executing.
|
||||||
execute_script();
|
execute_script();
|
||||||
|
|
|
@ -62,6 +62,13 @@ private:
|
||||||
bool m_ready_to_be_parser_executed { false };
|
bool m_ready_to_be_parser_executed { false };
|
||||||
bool m_failed_to_load { false };
|
bool m_failed_to_load { false };
|
||||||
|
|
||||||
|
enum class ScriptType {
|
||||||
|
Classic,
|
||||||
|
Module
|
||||||
|
};
|
||||||
|
|
||||||
|
ScriptType m_script_type { ScriptType::Classic };
|
||||||
|
|
||||||
Function<void()> m_script_ready_callback;
|
Function<void()> m_script_ready_callback;
|
||||||
|
|
||||||
String m_script_source;
|
String m_script_source;
|
||||||
|
|
|
@ -170,6 +170,7 @@ void HTMLDocumentParser::run(const URL& url)
|
||||||
|
|
||||||
auto scripts_to_execute_when_parsing_has_finished = m_document->take_scripts_to_execute_when_parsing_has_finished({});
|
auto scripts_to_execute_when_parsing_has_finished = m_document->take_scripts_to_execute_when_parsing_has_finished({});
|
||||||
for (auto& script : scripts_to_execute_when_parsing_has_finished) {
|
for (auto& script : scripts_to_execute_when_parsing_has_finished) {
|
||||||
|
// FIXME: Spin the event loop until the script is ready to be parser executed and there's no style sheets blocking scripts.
|
||||||
script.execute_script();
|
script.execute_script();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,6 +178,8 @@ void HTMLDocumentParser::run(const URL& url)
|
||||||
content_loaded_event->set_bubbles(true);
|
content_loaded_event->set_bubbles(true);
|
||||||
m_document->dispatch_event(content_loaded_event);
|
m_document->dispatch_event(content_loaded_event);
|
||||||
|
|
||||||
|
// FIXME: The document parser shouldn't execute these, it should just spin the event loop until the list becomes empty.
|
||||||
|
// FIXME: Once the set has been added, also spin the event loop until the set becomes empty.
|
||||||
auto scripts_to_execute_as_soon_as_possible = m_document->take_scripts_to_execute_as_soon_as_possible({});
|
auto scripts_to_execute_as_soon_as_possible = m_document->take_scripts_to_execute_as_soon_as_possible({});
|
||||||
for (auto& script : scripts_to_execute_as_soon_as_possible) {
|
for (auto& script : scripts_to_execute_as_soon_as_possible) {
|
||||||
script.execute_script();
|
script.execute_script();
|
||||||
|
@ -583,7 +586,7 @@ void HTMLDocumentParser::handle_in_head(HTMLToken& token)
|
||||||
script_element.set_non_blocking({}, false);
|
script_element.set_non_blocking({}, false);
|
||||||
|
|
||||||
if (m_parsing_fragment) {
|
if (m_parsing_fragment) {
|
||||||
TODO();
|
script_element.set_already_started({}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_invoked_via_document_write) {
|
if (m_invoked_via_document_write) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue