Skip to content

Commit

Permalink
<a>/<area>'s protocol setter incorrectly works for non-parsable URLs
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=260653
rdar://114371380

Reviewed by Chris Dumez.

We cannot use URLDecomposition's protocol setter directly as it does
not account for non-parsable URLs (not even indirectly, as most other
getter/setters do). Therefore check for non-parsable URLs in
HTMLAnchorElement before calling it.

New tests are being upstreamed through
web-platform-tests/wpt#41614.

* LayoutTests/imported/w3c/resources/import-expectations.json:
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/links/links-created-by-a-and-area-elements/non-parsable-url-getter-setter.window.html: Added.
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/links/links-created-by-a-and-area-elements/non-parsable-url-getter-setter.window.js: Added.
(string_appeared_here.forEach.name.get if.set test):
(string_appeared_here.forEach.name.get if):
(forEach.set string_appeared_here):
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/links/links-created-by-a-and-area-elements/non-special-opaque-path-url-getter-setter.window.html: Added.
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/links/links-created-by-a-and-area-elements/non-special-opaque-path-url-getter-setter.window.js: Added.
(string_appeared_here.forEach.name.get if.set test):
(string_appeared_here.forEach.name.get if):
(get string_appeared_here):
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/links/links-created-by-a-and-area-elements/non-special-url-getter-setter.window.html: Added.
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/links/links-created-by-a-and-area-elements/non-special-url-getter-setter.window.js: Added.
(string_appeared_here.forEach.name.get if.set test):
(string_appeared_here.forEach.name.get if):
(set string_appeared_here):
* LayoutTests/imported/w3c/web-platform-tests/html/semantics/links/links-created-by-a-and-area-elements/w3c-import.log:
* Source/WebCore/html/HTMLAnchorElement.cpp:
(WebCore::HTMLAnchorElement::setProtocol):
* Source/WebCore/html/HTMLAnchorElement.h:

Canonical link: https://commits.webkit.org/267265@main
  • Loading branch information
annevk committed Aug 25, 2023
1 parent 77752e9 commit 38e8e38
Show file tree
Hide file tree
Showing 13 changed files with 312 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@
"web-platform-tests/html/semantics/interactive-elements/the-summary-element": "skip",
"web-platform-tests/html/semantics/links/downloading-resources": "import",
"web-platform-tests/html/semantics/links/following-hyperlinks": "skip",
"web-platform-tests/html/semantics/links/links-created-by-a-and-area-elements": "skip",
"web-platform-tests/html/semantics/links/links-created-by-a-and-area-elements": "import",
"web-platform-tests/html/semantics/popovers": "import",
"web-platform-tests/html/semantics/scripting-1/the-script-element/css-module-assertions": "skip",
"web-platform-tests/html/semantics/scripting-1/the-script-element/execution-timing": "skip",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@

PASS <a href="http://test:test/">.origin getter
PASS <area href="http://test:test/">.origin getter
PASS <a href="http://test:test/">.protocol getter
PASS <a href="http://test:test/">.protocol setter
PASS <area href="http://test:test/">.protocol getter
PASS <area href="http://test:test/">.protocol setter
PASS <a href="http://test:test/">.username getter
PASS <a href="http://test:test/">.username setter
PASS <area href="http://test:test/">.username getter
PASS <area href="http://test:test/">.username setter
PASS <a href="http://test:test/">.password getter
PASS <a href="http://test:test/">.password setter
PASS <area href="http://test:test/">.password getter
PASS <area href="http://test:test/">.password setter
PASS <a href="http://test:test/">.host getter
PASS <a href="http://test:test/">.host setter
PASS <area href="http://test:test/">.host getter
PASS <area href="http://test:test/">.host setter
PASS <a href="http://test:test/">.hostname getter
PASS <a href="http://test:test/">.hostname setter
PASS <area href="http://test:test/">.hostname getter
PASS <area href="http://test:test/">.hostname setter
PASS <a href="http://test:test/">.port getter
PASS <a href="http://test:test/">.port setter
PASS <area href="http://test:test/">.port getter
PASS <area href="http://test:test/">.port setter
PASS <a href="http://test:test/">.pathname getter
PASS <a href="http://test:test/">.pathname setter
PASS <area href="http://test:test/">.pathname getter
PASS <area href="http://test:test/">.pathname setter
PASS <a href="http://test:test/">.search getter
PASS <a href="http://test:test/">.search setter
PASS <area href="http://test:test/">.search getter
PASS <area href="http://test:test/">.search setter
PASS <a href="http://test:test/">.hash getter
PASS <a href="http://test:test/">.hash setter
PASS <area href="http://test:test/">.hash getter
PASS <area href="http://test:test/">.hash setter

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<!-- This file is required for WebKit test infrastructure to run the templated test -->
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
[
{
"property": "origin",
"set": null
},
{
"property": "protocol",
"get": ":",
"set": "https"
},
{
"property": "username"
},
{
"property": "password"
},
{
"property": "host"
},
{
"property": "hostname"
},
{
"property": "port",
"set": "8000"
},
{
"property": "pathname"
},
{
"property": "search"
},
{
"property": "hash"
}
].forEach(({ property, get = "", set = "string" }) => {
["a", "area"].forEach(name => {
test(() => {
const link = document.createElement(name);
link.href = "http://test:test/"; // non-parsable URL
assert_equals(link[property], get);
}, `<${name} href="http://test:test/">.${property} getter`);

if (set !== null) {
test(() => {
const link = document.createElement(name);
link.href = "http://test:test/"; // non-parsable URL
link[property] = set;
assert_equals(link[property], get);
assert_equals(link.href, "http://test:test/");
}, `<${name} href="http://test:test/">.${property} setter`);
}
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@

PASS <a href="non-special:opaque">.origin getter
PASS <area href="non-special:opaque">.origin getter
PASS <a href="non-special:opaque">.protocol getter
PASS <a href="non-special:opaque">.protocol setter
PASS <area href="non-special:opaque">.protocol getter
PASS <area href="non-special:opaque">.protocol setter
PASS <a href="non-special:opaque">.username getter
PASS <a href="non-special:opaque">.username setter
PASS <area href="non-special:opaque">.username getter
PASS <area href="non-special:opaque">.username setter
PASS <a href="non-special:opaque">.password getter
PASS <a href="non-special:opaque">.password setter
PASS <area href="non-special:opaque">.password getter
PASS <area href="non-special:opaque">.password setter
PASS <a href="non-special:opaque">.host getter
PASS <a href="non-special:opaque">.host setter
PASS <area href="non-special:opaque">.host getter
PASS <area href="non-special:opaque">.host setter
PASS <a href="non-special:opaque">.hostname getter
PASS <a href="non-special:opaque">.hostname setter
PASS <area href="non-special:opaque">.hostname getter
PASS <area href="non-special:opaque">.hostname setter
PASS <a href="non-special:opaque">.port getter
PASS <a href="non-special:opaque">.port setter
PASS <area href="non-special:opaque">.port getter
PASS <area href="non-special:opaque">.port setter
PASS <a href="non-special:opaque">.pathname getter
PASS <a href="non-special:opaque">.pathname setter
PASS <area href="non-special:opaque">.pathname getter
PASS <area href="non-special:opaque">.pathname setter
PASS <a href="non-special:opaque">.search getter
PASS <a href="non-special:opaque">.search setter
PASS <area href="non-special:opaque">.search getter
PASS <area href="non-special:opaque">.search setter
PASS <a href="non-special:opaque">.hash getter
PASS <a href="non-special:opaque">.hash setter
PASS <area href="non-special:opaque">.hash getter
PASS <area href="non-special:opaque">.hash setter

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<!-- This file is required for WebKit test infrastructure to run the templated test -->
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
[
{
"property": "origin",
"get": "null",
"set": null
},
{
"property": "protocol",
"get": "non-special:",
"set": "super-special",
"setget": "super-special:"
},
{
"property": "username"
},
{
"property": "password"
},
{
"property": "host",
},
{
"property": "hostname",
},
{
"property": "port",
"set": "8000"
},
{
"property": "pathname",
"get": "opaque",
"setget": "opaque"
},
{
"property": "search",
"setget": "?string"
},
{
"property": "hash",
"setget": "#string"
}
].forEach(({ property, get = "", set = "string", setget = get }) => {
["a", "area"].forEach(name => {
test(() => {
const link = document.createElement(name);
link.href = "non-special:opaque";
assert_equals(link[property], get);
}, `<${name} href="non-special:opaque">.${property} getter`);

if (set !== null) {
test(() => {
const link = document.createElement(name);
link.href = "non-special:opaque";
link[property] = set;
assert_equals(link[property], setget);
}, `<${name} href="non-special:opaque">.${property} setter`);
}
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@

PASS <a href="non-special://test:9001/">.origin getter
PASS <area href="non-special://test:9001/">.origin getter
PASS <a href="non-special://test:9001/">.protocol getter
PASS <a href="non-special://test:9001/">.protocol setter
PASS <area href="non-special://test:9001/">.protocol getter
PASS <area href="non-special://test:9001/">.protocol setter
PASS <a href="non-special://test:9001/">.username getter
PASS <a href="non-special://test:9001/">.username setter
PASS <area href="non-special://test:9001/">.username getter
PASS <area href="non-special://test:9001/">.username setter
PASS <a href="non-special://test:9001/">.password getter
PASS <a href="non-special://test:9001/">.password setter
PASS <area href="non-special://test:9001/">.password getter
PASS <area href="non-special://test:9001/">.password setter
PASS <a href="non-special://test:9001/">.host getter
PASS <a href="non-special://test:9001/">.host setter
PASS <area href="non-special://test:9001/">.host getter
PASS <area href="non-special://test:9001/">.host setter
PASS <a href="non-special://test:9001/">.hostname getter
PASS <a href="non-special://test:9001/">.hostname setter
PASS <area href="non-special://test:9001/">.hostname getter
PASS <area href="non-special://test:9001/">.hostname setter
PASS <a href="non-special://test:9001/">.port getter
PASS <a href="non-special://test:9001/">.port setter
PASS <area href="non-special://test:9001/">.port getter
PASS <area href="non-special://test:9001/">.port setter
PASS <a href="non-special://test:9001/">.pathname getter
PASS <a href="non-special://test:9001/">.pathname setter
PASS <area href="non-special://test:9001/">.pathname getter
PASS <area href="non-special://test:9001/">.pathname setter
PASS <a href="non-special://test:9001/">.search getter
PASS <a href="non-special://test:9001/">.search setter
PASS <area href="non-special://test:9001/">.search getter
PASS <area href="non-special://test:9001/">.search setter
PASS <a href="non-special://test:9001/">.hash getter
PASS <a href="non-special://test:9001/">.hash setter
PASS <area href="non-special://test:9001/">.hash getter
PASS <area href="non-special://test:9001/">.hash setter

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<!-- This file is required for WebKit test infrastructure to run the templated test -->
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
[
{
"property": "origin",
"get": "null",
"set": null
},
{
"property": "protocol",
"get": "non-special:",
"set": "super-special",
"setget": "super-special:"
},
{
"property": "username"
},
{
"property": "password"
},
{
"property": "host",
"get": "test:9001",
"setget": "string:9001"
},
{
"property": "hostname",
"get": "test"
},
{
"property": "port",
"get": "9001",
"set": "8000"
},
{
"property": "pathname",
"get": "/",
"setget": "/string"
},
{
"property": "search",
"setget": "?string"
},
{
"property": "hash",
"setget": "#string"
}
].forEach(({ property, get = "", set = "string", setget = set }) => {
["a", "area"].forEach(name => {
test(() => {
const link = document.createElement(name);
link.href = "non-special://test:9001/";
assert_equals(link[property], get);
}, `<${name} href="non-special://test:9001/">.${property} getter`);

if (set !== null) {
test(() => {
const link = document.createElement(name);
link.href = "non-special://test:9001/";
link[property] = set;
assert_equals(link[property], setget);
}, `<${name} href="non-special://test:9001/">.${property} setter`);
}
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,8 @@ List of files:
/LayoutTests/imported/w3c/web-platform-tests/html/semantics/links/links-created-by-a-and-area-elements/htmlanchorelement_attribute-getter-setter.html
/LayoutTests/imported/w3c/web-platform-tests/html/semantics/links/links-created-by-a-and-area-elements/htmlanchorelement_getter.html
/LayoutTests/imported/w3c/web-platform-tests/html/semantics/links/links-created-by-a-and-area-elements/htmlanchorelement_noopener.html
/LayoutTests/imported/w3c/web-platform-tests/html/semantics/links/links-created-by-a-and-area-elements/non-parsable-url-getter-setter.window.js
/LayoutTests/imported/w3c/web-platform-tests/html/semantics/links/links-created-by-a-and-area-elements/non-special-opaque-path-url-getter-setter.window.js
/LayoutTests/imported/w3c/web-platform-tests/html/semantics/links/links-created-by-a-and-area-elements/non-special-url-getter-setter.window.js
/LayoutTests/imported/w3c/web-platform-tests/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener.html
/LayoutTests/imported/w3c/web-platform-tests/html/semantics/links/links-created-by-a-and-area-elements/target_blank_implicit_noopener_base.html
7 changes: 7 additions & 0 deletions Source/WebCore/html/HTMLAnchorElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,13 @@ String HTMLAnchorElement::origin() const
return SecurityOrigin::create(url)->toString();
}

void HTMLAnchorElement::setProtocol(StringView value)
{
if (auto url = href(); !url.isValid())
return;
URLDecomposition::setProtocol(value);
}

String HTMLAnchorElement::text()
{
return textContent();
Expand Down
2 changes: 2 additions & 0 deletions Source/WebCore/html/HTMLAnchorElement.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ class HTMLAnchorElement : public HTMLElement, public URLDecomposition {

WEBCORE_EXPORT String origin() const;

WEBCORE_EXPORT void setProtocol(StringView value);

WEBCORE_EXPORT String text();
void setText(String&&);

Expand Down

0 comments on commit 38e8e38

Please sign in to comment.