From 0eac8bce6f7ebe88b6e6dd4c8ddfe5e2c3dd52b7 Mon Sep 17 00:00:00 2001 From: PrestonLTaylor <95388976+PrestonLTaylor@users.noreply.github.com> Date: Mon, 26 Jun 2023 20:04:14 +0100 Subject: [PATCH] LibWeb: Fix js execution for js urls in anchor tags href --- Userland/Libraries/LibWeb/DOM/Document.cpp | 45 ++++++++++++------- Userland/Libraries/LibWeb/DOM/Document.h | 3 +- .../LibWeb/HTML/HTMLAnchorElement.cpp | 5 +++ .../Libraries/LibWeb/Page/EventHandler.cpp | 2 +- 4 files changed, 38 insertions(+), 17 deletions(-) diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index 48ee500b05f..5048c880c37 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -67,6 +67,7 @@ #include #include #include +#include #include #include #include @@ -1282,25 +1283,39 @@ HTML::EnvironmentSettingsObject& Document::relevant_settings_object() return Bindings::host_defined_environment_settings_object(realm()); } -JS::Value Document::run_javascript(StringView source, StringView filename) +// https://html.spec.whatwg.org/multipage/browsing-the-web.html#navigate-to-a-javascript:-url +void Document::navigate_to_javascript_url(StringView url) { - // FIXME: The only user of this function now is javascript: URLs. Refactor them to follow the spec: https://html.spec.whatwg.org/multipage/browsing-the-web.html#javascript-protocol - auto interpreter = JS::Interpreter::create_with_existing_realm(realm()); - auto script_or_error = JS::Script::parse(source, realm(), filename); - if (script_or_error.is_error()) { - // FIXME: Add error logging back. - return JS::js_undefined(); - } + // FIXME: Implement the rest of steps from the spec - auto result = interpreter->run(script_or_error.value()); + // 6. Let newDocument be the result of evaluating a javascript: URL given targetNavigable, url, and initiatorOrigin. + evaluate_javascript_url(url); +} - if (result.is_error()) { - // FIXME: I'm sure the spec could tell us something about error propagation here! - HTML::report_exception(result, realm()); +// https://html.spec.whatwg.org/multipage/browsing-the-web.html#evaluate-a-javascript:-url +void Document::evaluate_javascript_url(StringView url) +{ + // NOTE: This is done by EventHandler::handle_mouseup + // 1. Let urlString be the result of running the URL serializer on url. - return {}; - } - return result.value(); + // 2. Let encodedScriptSource be the result of removing the leading "javascript:" from urlString. + auto encoded_script_source = url.substring_view(11, url.length() - 11); + + // FIXME: 3. Let scriptSource be the UTF-8 decoding of the percent-decoding of encodedScriptSource. + + // 4. Let settings be targetNavigable's active document's relevant settings object. + auto& settings = relevant_settings_object(); + + // 5. Let baseURL be settings's API base URL. + auto base_url = settings.api_base_url(); + + // 6. Let script be the result of creating a classic script given scriptSource, settings, baseURL, and the default classic script fetch options. + auto script = HTML::ClassicScript::create("(javascript url)", encoded_script_source, settings, base_url); + + // 7. Let evaluationStatus be the result of running the classic script script. + static_cast(script->run()); + + // FIXME: Implement the rest of the steps from the spec } // https://dom.spec.whatwg.org/#dom-document-createelement diff --git a/Userland/Libraries/LibWeb/DOM/Document.h b/Userland/Libraries/LibWeb/DOM/Document.h index 24ee0d570ef..b5e7139716c 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.h +++ b/Userland/Libraries/LibWeb/DOM/Document.h @@ -231,7 +231,8 @@ public: HTML::EnvironmentSettingsObject& relevant_settings_object(); - JS::Value run_javascript(StringView source, StringView filename = "(unknown)"sv); + void navigate_to_javascript_url(StringView url); + void evaluate_javascript_url(StringView url); WebIDL::ExceptionOr> create_element(DeprecatedString const& local_name, Variant const& options); WebIDL::ExceptionOr> create_element_ns(DeprecatedString const& namespace_, DeprecatedString const& qualified_name, Variant const& options); diff --git a/Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.cpp index 79911384359..88085f7b578 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLAnchorElement.cpp @@ -55,6 +55,11 @@ void HTMLAnchorElement::run_activation_behavior(Web::DOM::Event const&) if (href().is_empty()) return; + // AD-HOC: follow_the_hyperlink currently doesn't navigate properly with javascript urls + // EventHandler::handle_mouseup performs the navigation steps for javascript urls instead + if (href().starts_with("javascript:"sv)) + return; + // 2. Let hyperlinkSuffix be null. Optional hyperlink_suffix {}; diff --git a/Userland/Libraries/LibWeb/Page/EventHandler.cpp b/Userland/Libraries/LibWeb/Page/EventHandler.cpp index 5685b283f30..6929489897a 100644 --- a/Userland/Libraries/LibWeb/Page/EventHandler.cpp +++ b/Userland/Libraries/LibWeb/Page/EventHandler.cpp @@ -286,7 +286,7 @@ bool EventHandler::handle_mouseup(CSSPixelPoint position, unsigned button, unsig dbgln("Web::EventHandler: Clicking on a link to {}", url); if (button == GUI::MouseButton::Primary) { if (href.starts_with("javascript:"sv)) { - document->run_javascript(href.substring_view(11, href.length() - 11)); + document->navigate_to_javascript_url(href); } else if (!url.fragment().is_null() && url.equals(document->url(), AK::URL::ExcludeFragment::Yes)) { m_browsing_context->scroll_to_anchor(url.fragment()); } else {