mirror of
https://github.com/lexmount/moli.git
synced 2026-10-06 08:00:59 +00:00
fix(url): expose colon protocol for invalid hyperlinks
This commit is contained in:
@@ -1992,6 +1992,7 @@ struct HtmlTableElementPrototypeDeclaration {
|
||||
fn anchor_url_string_function_getter<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
receiver: v8::Local<'s, v8::Object>,
|
||||
parse_failure_value: &'static str,
|
||||
project: impl FnOnce(&url::Url) -> String,
|
||||
mut rv: v8::ReturnValue<'_, v8::Value>,
|
||||
) {
|
||||
@@ -2003,7 +2004,7 @@ fn anchor_url_string_function_getter<'s>(
|
||||
};
|
||||
let value = parsed_url_like_attribute(unsafe { &*runtime_ptr }, handle, "href")
|
||||
.map(|url| project(&url))
|
||||
.unwrap_or_default();
|
||||
.unwrap_or_else(|| parse_failure_value.to_owned());
|
||||
if let Some(value) = v8_string(scope, &value) {
|
||||
rv.set(value.into());
|
||||
} else {
|
||||
@@ -2269,6 +2270,7 @@ fn anchor_host_getter_function<'s>(
|
||||
anchor_url_string_function_getter(
|
||||
scope,
|
||||
args.this(),
|
||||
"",
|
||||
|url| {
|
||||
url.host_str()
|
||||
.map(|host| {
|
||||
@@ -2325,6 +2327,7 @@ fn anchor_hostname_getter_function<'s>(
|
||||
anchor_url_string_function_getter(
|
||||
scope,
|
||||
args.this(),
|
||||
"",
|
||||
|url| url.host_str().unwrap_or_default().to_owned(),
|
||||
rv,
|
||||
);
|
||||
@@ -2357,6 +2360,7 @@ fn anchor_port_getter_function<'s>(
|
||||
anchor_url_string_function_getter(
|
||||
scope,
|
||||
args.this(),
|
||||
"",
|
||||
|url| url.port().map(|port| port.to_string()).unwrap_or_default(),
|
||||
rv,
|
||||
);
|
||||
@@ -2386,7 +2390,7 @@ fn anchor_pathname_getter_function<'s>(
|
||||
args: v8::FunctionCallbackArguments<'s>,
|
||||
rv: v8::ReturnValue<'_, v8::Value>,
|
||||
) {
|
||||
anchor_url_string_function_getter(scope, args.this(), |url| url.path().to_owned(), rv);
|
||||
anchor_url_string_function_getter(scope, args.this(), "", |url| url.path().to_owned(), rv);
|
||||
}
|
||||
|
||||
fn anchor_pathname_setter_function<'s>(
|
||||
@@ -2415,6 +2419,7 @@ fn anchor_search_getter_function<'s>(
|
||||
anchor_url_string_function_getter(
|
||||
scope,
|
||||
args.this(),
|
||||
"",
|
||||
|url| url::quirks::search(url).to_owned(),
|
||||
rv,
|
||||
);
|
||||
@@ -2443,6 +2448,7 @@ fn anchor_hash_getter_function<'s>(
|
||||
anchor_url_string_function_getter(
|
||||
scope,
|
||||
args.this(),
|
||||
"",
|
||||
|url| url::quirks::hash(url).to_owned(),
|
||||
rv,
|
||||
);
|
||||
@@ -2468,7 +2474,13 @@ fn anchor_origin_getter_function<'s>(
|
||||
args: v8::FunctionCallbackArguments<'s>,
|
||||
rv: v8::ReturnValue<'_, v8::Value>,
|
||||
) {
|
||||
anchor_url_string_function_getter(scope, args.this(), moli_url::origin_ascii_serialization, rv);
|
||||
anchor_url_string_function_getter(
|
||||
scope,
|
||||
args.this(),
|
||||
"",
|
||||
moli_url::origin_ascii_serialization,
|
||||
rv,
|
||||
);
|
||||
}
|
||||
|
||||
fn anchor_protocol_getter_function<'s>(
|
||||
@@ -2476,7 +2488,13 @@ fn anchor_protocol_getter_function<'s>(
|
||||
args: v8::FunctionCallbackArguments<'s>,
|
||||
rv: v8::ReturnValue<'_, v8::Value>,
|
||||
) {
|
||||
anchor_url_string_function_getter(scope, args.this(), |url| format!("{}:", url.scheme()), rv);
|
||||
anchor_url_string_function_getter(
|
||||
scope,
|
||||
args.this(),
|
||||
":",
|
||||
|url| format!("{}:", url.scheme()),
|
||||
rv,
|
||||
);
|
||||
}
|
||||
|
||||
fn anchor_protocol_setter_function<'s>(
|
||||
@@ -2500,7 +2518,7 @@ fn anchor_username_getter_function<'s>(
|
||||
args: v8::FunctionCallbackArguments<'s>,
|
||||
rv: v8::ReturnValue<'_, v8::Value>,
|
||||
) {
|
||||
anchor_url_string_function_getter(scope, args.this(), |url| url.username().to_owned(), rv);
|
||||
anchor_url_string_function_getter(scope, args.this(), "", |url| url.username().to_owned(), rv);
|
||||
}
|
||||
|
||||
fn anchor_username_setter_function<'s>(
|
||||
@@ -2529,6 +2547,7 @@ fn anchor_password_getter_function<'s>(
|
||||
anchor_url_string_function_getter(
|
||||
scope,
|
||||
args.this(),
|
||||
"",
|
||||
|url| url.password().unwrap_or("").to_owned(),
|
||||
rv,
|
||||
);
|
||||
|
||||
+42
@@ -718,6 +718,48 @@ fn detached_specialized_url_resource_properties_use_owner_prototypes() {
|
||||
assert_eq!(result, "ok");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hyperlink_protocol_is_colon_when_href_cannot_be_parsed() {
|
||||
let mut vm = new_storage_test_vm("https://hyperlink-invalid-url.test/page.html");
|
||||
|
||||
let result = vm
|
||||
.eval(
|
||||
r#"
|
||||
(() => {
|
||||
const base = document.createElement("base");
|
||||
base.href = "about:blank";
|
||||
(document.head || document.documentElement || document).appendChild(base);
|
||||
const inputs = [
|
||||
"",
|
||||
"javascript://:443",
|
||||
"javascript://test:test",
|
||||
"javascript://[:1]",
|
||||
"mailto://:443",
|
||||
"mailto://test:test",
|
||||
"mailto://[:1]"
|
||||
];
|
||||
|
||||
for (const tag of ["a", "area"]) {
|
||||
const element = document.createElement(tag);
|
||||
for (const input of inputs) {
|
||||
element.setAttribute("href", input);
|
||||
if (element.href !== input) {
|
||||
throw new Error(`${tag} should preserve the unparsable href ${input}`);
|
||||
}
|
||||
if (element.protocol !== ":") {
|
||||
throw new Error(`${tag} should expose ':' for the unparsable href ${input}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
return "ok";
|
||||
})()
|
||||
"#,
|
||||
)
|
||||
.expect("unparsable hyperlink protocol probe should evaluate");
|
||||
|
||||
assert_eq!(result, "ok");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hyperlink_stringifiers_use_native_href_and_enforce_owner_brand() {
|
||||
let mut vm = new_storage_test_vm("https://hyperlink-stringifier.test/base/page.html");
|
||||
|
||||
Reference in New Issue
Block a user