Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LibWeb: Load external scripts in SVG #2738

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 38 additions & 17 deletions Libraries/LibWeb/SVG/SVGScriptElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

#include <LibWeb/Bindings/SVGScriptElementPrototype.h>
#include <LibWeb/HTML/Scripting/ClassicScript.h>
#include <LibWeb/Loader/LoadRequest.h>
#include <LibWeb/Loader/ResourceLoader.h>
#include <LibWeb/Namespace.h>
#include <LibWeb/SVG/AttributeNames.h>
#include <LibWeb/SVG/SVGScriptElement.h>
Expand Down Expand Up @@ -40,33 +42,52 @@ void SVGScriptElement::process_the_script_element()
if (m_already_processed || !in_a_document_tree())
return;

auto inline_script = child_text_content();
String script_content;
auto script_url = m_document->url();

// FIXME: 2. If the 'script' element references external script content, then the external script content
// using the current value of the 'xlink:href' attribute is fetched. Further processing of the
// 'script' element is dependent on the external script content, and will block here until the
// resource has been fetched or is determined to be an invalid IRI reference.
// 2. If the 'script' element references external script content, then the external script content
// using the current value of the 'xlink:href' attribute is fetched. Further processing of the
// 'script' element is dependent on the external script content, and will block here until the
// resource has been fetched or is determined to be an invalid IRI reference.
if (has_attribute(SVG::AttributeNames::href) || has_attribute_ns(Namespace::XLink.to_string(), SVG::AttributeNames::href)) {
dbgln("FIXME: Unsupported external fetch of SVGScriptElement!");
return;
auto href_value = href()->base_val();

script_url = document().parse_url(href_value);
if (!script_url.is_valid()) {
// Handle invalid IRI reference
dbgln("Invalid script URL: {}", href_value);
return;
}

// Fetch the external script content
auto request = LoadRequest::create_for_url_on_page(script_url, &document().page());
auto resource = ResourceLoader::the().load_resource(Resource::Type::Generic, request);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be updated to use fetch, see: #2634

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like a right thing to do, but looks overcomplicated. I haven't found a simple few-lines way to do that (yet)


// Block until the resource has been fetched or determined invalid
HTML::main_thread_event_loop().spin_until(GC::create_function(heap(), [&] { return resource->is_loaded(); }));

auto script_content_or_error = String::from_utf8(resource->encoded_data());
if (script_content_or_error.is_error()) {
dbgln("Failed to decode script content as UTF-8");
return;
}
script_content = script_content_or_error.release_value();
} else {
// Inline script content
script_content = child_text_content();
}

// 3. The 'script' element's "already processed" flag is set to true.
m_already_processed = true;

// 4. If the script content is inline, or if it is external and was fetched successfully, then the
// script is executed. Note that at this point, these steps may be re-entrant if the execution
// of the script results in further 'script' elements being inserted into the document.

// https://html.spec.whatwg.org/multipage/document-lifecycle.html#read-html
// Before any script execution occurs, the user agent must wait for scripts may run for the newly-created document to be true for document.
// 4. If the script content is inline, or if it is external and was fetched successfully,
// then the script is executed.
// Note that at this point, these steps may be re-entrant if the execution of the script results
// in further 'script' elements being inserted into the document.
if (!m_document->ready_to_run_scripts())
HTML::main_thread_event_loop().spin_until(GC::create_function(heap(), [&] { return m_document->ready_to_run_scripts(); }));

// FIXME: Support non-inline scripts.
auto base_url = document().base_url();

m_script = HTML::ClassicScript::create(m_document->url().to_byte_string(), inline_script, realm(), base_url, m_source_line_number);
m_script = HTML::ClassicScript::create(script_url.to_byte_string(), script_content, realm(), document().base_url(), m_source_line_number);
(void)m_script->run();
}

Expand Down
Loading