From 5a7fd1de418b1379c535b3e196f1825f50877e11 Mon Sep 17 00:00:00 2001
From: Niels Dossche <7771979+nielsdos@users.noreply.github.com>
Date: Sat, 25 Oct 2025 11:15:34 +0200
Subject: [PATCH 1/5] Make bug70417.phpt less flaky
---
ext/phar/tests/tar/bug70417.phpt | 21 +++------------------
1 file changed, 3 insertions(+), 18 deletions(-)
diff --git a/ext/phar/tests/tar/bug70417.phpt b/ext/phar/tests/tar/bug70417.phpt
index 4d98a18954cc..504d7e1e387b 100644
--- a/ext/phar/tests/tar/bug70417.phpt
+++ b/ext/phar/tests/tar/bug70417.phpt
@@ -3,32 +3,17 @@ Bug #70417 (PharData::compress() doesn't close temp file)
--EXTENSIONS--
phar
zlib
---SKIPIF--
-
--FILE--
/dev/null', $out); // Note: valgrind can produce false positives for /usr/bin/lsof
- return count($out);
-}
$filename = __DIR__ . '/bug70417.tar';
@unlink("$filename.gz");
-$openFiles1 = countOpenFiles();
+$resBefore = count(get_resources());
$arch = new PharData($filename);
$arch->addFromString('foo', 'bar');
$arch->compress(Phar::GZ);
unset($arch);
-$openFiles2 = countOpenFiles();
-var_dump($openFiles1 === $openFiles2);
+$resAfter = count(get_resources());
+var_dump($resBefore === $resAfter);
?>
--CLEAN--
Date: Sat, 25 Oct 2025 11:15:34 +0200
Subject: [PATCH 2/5] Make bug70417.phpt less flaky
Closes GH-20287.
---
ext/phar/tests/tar/bug70417.phpt | 21 +++------------------
1 file changed, 3 insertions(+), 18 deletions(-)
diff --git a/ext/phar/tests/tar/bug70417.phpt b/ext/phar/tests/tar/bug70417.phpt
index 4d98a18954cc..504d7e1e387b 100644
--- a/ext/phar/tests/tar/bug70417.phpt
+++ b/ext/phar/tests/tar/bug70417.phpt
@@ -3,32 +3,17 @@ Bug #70417 (PharData::compress() doesn't close temp file)
--EXTENSIONS--
phar
zlib
---SKIPIF--
-
--FILE--
/dev/null', $out); // Note: valgrind can produce false positives for /usr/bin/lsof
- return count($out);
-}
$filename = __DIR__ . '/bug70417.tar';
@unlink("$filename.gz");
-$openFiles1 = countOpenFiles();
+$resBefore = count(get_resources());
$arch = new PharData($filename);
$arch->addFromString('foo', 'bar');
$arch->compress(Phar::GZ);
unset($arch);
-$openFiles2 = countOpenFiles();
-var_dump($openFiles1 === $openFiles2);
+$resAfter = count(get_resources());
+var_dump($resBefore === $resAfter);
?>
--CLEAN--
Date: Fri, 24 Oct 2025 21:17:00 +0200
Subject: [PATCH 3/5] Fix GH-20281: \Dom\Document::getElementById() is
inconsistent after nodes are removed
This worked for non-parsed elements already, but not for elements where
xmlAddID() returns early due to the ID already existing.
In that case what was missing is marking the attribute as an ID.
Closes GH-20283.
---
NEWS | 2 ++
ext/dom/html5_parser.c | 5 ++++-
.../tests/modern/html/interactions/gh20281.phpt | 15 +++++++++++++++
3 files changed, 21 insertions(+), 1 deletion(-)
create mode 100644 ext/dom/tests/modern/html/interactions/gh20281.phpt
diff --git a/NEWS b/NEWS
index 1a7af0a2eb1b..35f06bd93b24 100644
--- a/NEWS
+++ b/NEWS
@@ -15,6 +15,8 @@ PHP NEWS
- DOM:
. Partially fixed bug GH-16317 (DOM classes do not allow
__debugInfo() overrides to work). (nielsdos)
+ . Fixed bug GH-20281 (\Dom\Document::getElementById() is inconsistent
+ after nodes are removed). (nielsdos)
- Exif:
. Fix possible memory leak when tag is empty. (nielsdos)
diff --git a/ext/dom/html5_parser.c b/ext/dom/html5_parser.c
index f1dc2db53b25..d5fe3d5c2773 100644
--- a/ext/dom/html5_parser.c
+++ b/ext/dom/html5_parser.c
@@ -268,7 +268,10 @@ static lexbor_libxml2_bridge_status lexbor_libxml2_bridge_convert(
/* xmlIsID does some other stuff too that is irrelevant here. */
if (local_name_length == 2 && local_name[0] == 'i' && local_name[1] == 'd' && attr->node.ns == LXB_NS_HTML) {
- xmlAddID(NULL, lxml_doc, value, lxml_attr);
+ if (xmlAddID(NULL, lxml_doc, value, lxml_attr) == 0) {
+ /* If the ID already exists, the ID attribute still needs to be marked as an ID. */
+ lxml_attr->atype = XML_ATTRIBUTE_ID;
+ }
}
/* libxml2 doesn't support line numbers on this anyway, it derives them instead, so don't bother */
diff --git a/ext/dom/tests/modern/html/interactions/gh20281.phpt b/ext/dom/tests/modern/html/interactions/gh20281.phpt
new file mode 100644
index 000000000000..324c5a275633
--- /dev/null
+++ b/ext/dom/tests/modern/html/interactions/gh20281.phpt
@@ -0,0 +1,15 @@
+--TEST--
+GH-20281 (\Dom\Document::getElementById() is inconsistent after nodes are removed)
+--EXTENSIONS--
+dom
+--CREDITS--
+cscott
+--FILE--
+b
c
', LIBXML_NOERROR);
+$p = $d->getElementById('a');
+$p->remove();
+echo $d->getElementById('a')->textContent, "\n";
+?>
+--EXPECT--
+c
From 0af4f27981025dd27a35bac946862ef83fe8ab52 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?=
Date: Sat, 25 Oct 2025 14:38:52 +0200
Subject: [PATCH 4/5] Fix GH-20274 SoapClient::__doRequest undocumented
backwards incompatible in PHP 8.5 (#20278)
---
NEWS | 2 +-
UPGRADING | 4 ++++
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/NEWS b/NEWS
index dd46f907d09e..23933494c825 100644
--- a/NEWS
+++ b/NEWS
@@ -354,7 +354,7 @@ PHP NEWS
. Added support for partitioned cookies. (nielsdos)
- SOAP:
- . Added support for configuring the URI parser for SoapClient::_doRequest()
+ . Added support for configuring the URI parser for SoapClient::__doRequest()
as described in https://wiki.php.net/rfc/url_parsing_api#plugability.
(kocsismate)
diff --git a/UPGRADING b/UPGRADING
index a196757eb9ac..b0f3c9155b31 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -170,6 +170,10 @@ PHP 8.5 UPGRADE NOTES
precision previously incorrectly reset the precision instead of treating
it as a precision of 0. See GH-18897.
+- SOAP:
+ . SoapClient::__doRequest() expects a new, optional $uriParserClass parameter
+ as described in https://wiki.php.net/rfc/url_parsing_api#plugability.
+
========================================
2. New Features
========================================
From 27bc7c0e1294eb0ce87f071acd42f43f01877d61 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?=
Date: Sat, 25 Oct 2025 14:46:06 +0200
Subject: [PATCH 5/5] Reorganize ext/uri tests - withers (#19970)
---
.../modification/fragment_error_reserved.phpt | 18 ++++++++++++++
.../modification/fragment_error_unicode.phpt | 18 ++++++++++++++
.../modification/fragment_success_empty.phpt | 23 ++++++++++++++++++
.../fragment_success_encoded.phpt | 23 ++++++++++++++++++
.../fragment_success_existing.phpt | 23 ++++++++++++++++++
.../fragment_success_unset_existing.phpt | 23 ++++++++++++++++++
.../fragment_success_unset_non_existent.phpt | 23 ++++++++++++++++++
.../modification/host_error_reserved.phpt | 18 ++++++++++++++
.../modification/host_success_empty.phpt | 23 ++++++++++++++++++
.../modification/host_success_encoded.phpt | 23 ++++++++++++++++++
.../modification/host_success_existing.phpt | 23 ++++++++++++++++++
.../modification/host_success_ip_future.phpt | 23 ++++++++++++++++++
.../modification/host_success_ipv4.phpt | 23 ++++++++++++++++++
.../modification/host_success_ipv6.phpt | 23 ++++++++++++++++++
.../modification/host_success_new.phpt | 23 ++++++++++++++++++
.../host_success_unset_existing.phpt | 23 ++++++++++++++++++
.../host_success_unset_non_existent.phpt | 23 ++++++++++++++++++
.../modification/path_error_reserved.phpt | 18 ++++++++++++++
.../modification/path_error_unicode.phpt | 18 ++++++++++++++
.../path_error_without_leading_slash.phpt | 18 ++++++++++++++
.../modification/path_success_email.phpt | 23 ++++++++++++++++++
.../modification/path_success_empty.phpt | 23 ++++++++++++++++++
.../modification/path_success_encoded.phpt | 23 ++++++++++++++++++
.../modification/path_success_existing.phpt | 23 ++++++++++++++++++
.../modification/port_error_negative.phpt | 18 ++++++++++++++
.../modification/port_success_existing.phpt | 19 +++++++++++++++
.../modification/port_success_new.phpt | 19 +++++++++++++++
.../port_success_unset_existing.phpt | 19 +++++++++++++++
.../port_success_unset_non_existent.phpt | 19 +++++++++++++++
.../modification/query_error_reserved.phpt | 18 ++++++++++++++
.../modification/query_error_unicode.phpt | 18 ++++++++++++++
...ry_success_context_sensitive_reserved.phpt | 23 ++++++++++++++++++
.../modification/query_success_empty.phpt | 23 ++++++++++++++++++
.../modification/query_success_encoded.phpt | 23 ++++++++++++++++++
.../modification/query_success_existing.phpt | 23 ++++++++++++++++++
.../query_success_unset_existing.phpt | 23 ++++++++++++++++++
.../query_success_unset_non_existent.phpt | 23 ++++++++++++++++++
.../modification/roundtrip_special_case1.phpt | 24 +++++++++++++++++++
.../modification/roundtrip_special_case2.phpt | 20 ++++++++++++++++
.../modification/roundtrip_special_case3.phpt | 20 ++++++++++++++++
.../modification/scheme_error_empty.phpt | 18 ++++++++++++++
.../modification/scheme_error_encoded.phpt | 18 ++++++++++++++
.../modification/scheme_error_reserved.phpt | 18 ++++++++++++++
.../modification/scheme_success_basic.phpt | 23 ++++++++++++++++++
.../scheme_success_unset_existing.phpt | 23 ++++++++++++++++++
.../scheme_success_unset_non_existent.phpt | 23 ++++++++++++++++++
.../modification/userinfo_error_reserved.phpt | 18 ++++++++++++++
.../modification/userinfo_success_empty.phpt | 19 +++++++++++++++
.../userinfo_success_encoded.phpt | 23 ++++++++++++++++++
.../userinfo_success_existing.phpt | 23 ++++++++++++++++++
.../modification/userinfo_success_new.phpt | 23 ++++++++++++++++++
.../userinfo_success_unset_existing.phpt | 23 ++++++++++++++++++
.../userinfo_success_unset_non_existent.phpt | 23 ++++++++++++++++++
.../fragment_success_auto_encode.phpt | 19 +++++++++++++++
.../modification/fragment_success_empty.phpt | 19 +++++++++++++++
.../fragment_success_encoded.phpt | 19 +++++++++++++++
.../fragment_success_existing.phpt | 19 +++++++++++++++
.../fragment_success_hashmark.phpt | 19 +++++++++++++++
.../fragment_success_unicode.phpt | 19 +++++++++++++++
.../fragment_success_unset_existing.phpt | 19 +++++++++++++++
.../fragment_success_unset_non_existent.phpt | 19 +++++++++++++++
...ragment_success_with_leading_hashmark.phpt | 19 +++++++++++++++
.../whatwg/modification/host_error_empty.phpt | 18 ++++++++++++++
...rror_forbidden_host_codepoint_opaque1.phpt | 18 ++++++++++++++
...rror_forbidden_host_codepoint_opaque2.phpt | 17 +++++++++++++
...rror_forbidden_host_codepoint_opaque3.phpt | 17 +++++++++++++
...ror_forbidden_host_codepoint_special1.phpt | 18 ++++++++++++++
...ror_forbidden_host_codepoint_special2.phpt | 18 ++++++++++++++
...ror_forbidden_host_codepoint_special3.phpt | 18 ++++++++++++++
.../host_error_unset_existing.phpt | 18 ++++++++++++++
.../modification/host_success_encoded.phpt | 19 +++++++++++++++
.../modification/host_success_existing.phpt | 19 +++++++++++++++
.../modification/host_success_idna.phpt | 23 ++++++++++++++++++
.../modification/host_success_ipv4.phpt | 19 +++++++++++++++
.../modification/host_success_ipv6.phpt | 19 +++++++++++++++
.../password_success_auto_encoded.phpt | 19 +++++++++++++++
.../modification/password_success_empty.phpt | 19 +++++++++++++++
.../password_success_encoded.phpt | 19 +++++++++++++++
.../password_success_existing.phpt | 19 +++++++++++++++
.../modification/password_success_new.phpt | 19 +++++++++++++++
.../password_success_unset_existing.phpt | 19 +++++++++++++++
.../password_success_unset_non_existent1.phpt | 19 +++++++++++++++
.../password_success_unset_non_existent2.phpt | 19 +++++++++++++++
.../path_success_auto_encoded.phpt | 19 +++++++++++++++
.../modification/path_success_empty.phpt | 19 +++++++++++++++
.../modification/path_success_encoded.phpt | 19 +++++++++++++++
.../modification/path_success_existing.phpt | 19 +++++++++++++++
.../modification/path_success_unicode.phpt | 18 ++++++++++++++
.../path_success_without_leading_slash.phpt | 19 +++++++++++++++
.../modification/port_error_negative.phpt | 18 ++++++++++++++
.../modification/port_error_too_large.phpt | 18 ++++++++++++++
.../modification/port_success_existing.phpt | 19 +++++++++++++++
.../whatwg/modification/port_success_new.phpt | 19 +++++++++++++++
.../modification/port_success_special1.phpt | 19 +++++++++++++++
.../modification/port_success_special2.phpt | 19 +++++++++++++++
.../port_success_unset_existing.phpt | 19 +++++++++++++++
.../port_success_unset_non_existent.phpt | 19 +++++++++++++++
.../query_success_auto_encoded.phpt | 19 +++++++++++++++
...ry_success_context_sensitive_reserved.phpt | 19 +++++++++++++++
.../modification/query_success_empty.phpt | 19 +++++++++++++++
.../modification/query_success_encoded.phpt | 19 +++++++++++++++
.../modification/query_success_existing.phpt | 19 +++++++++++++++
.../query_success_question_mark.phpt | 19 +++++++++++++++
.../modification/query_success_unicode.phpt | 19 +++++++++++++++
.../query_success_unset_existing.phpt | 19 +++++++++++++++
.../query_success_unset_non_existent.phpt | 19 +++++++++++++++
...ry_success_with_leading_question_mark.phpt | 19 +++++++++++++++
.../modification/scheme_error_empty.phpt | 18 ++++++++++++++
.../modification/scheme_error_encoded.phpt | 18 ++++++++++++++
.../modification/scheme_error_invalid.phpt | 18 ++++++++++++++
.../modification/scheme_success_basic.phpt | 19 +++++++++++++++
.../modification/scheme_success_colon.phpt | 19 +++++++++++++++
.../modification/scheme_success_full.phpt | 19 +++++++++++++++
.../username_success_auto_encoded.phpt | 19 +++++++++++++++
.../username_success_existing.phpt | 19 +++++++++++++++
.../modification/username_success_new.phpt | 19 +++++++++++++++
.../username_success_unset_existing.phpt | 19 +++++++++++++++
.../username_success_unset_non_existent1.phpt | 19 +++++++++++++++
.../username_success_unset_non_existent2.phpt | 19 +++++++++++++++
119 files changed, 2371 insertions(+)
create mode 100644 ext/uri/tests/rfc3986/modification/fragment_error_reserved.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/fragment_error_unicode.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/fragment_success_empty.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/fragment_success_encoded.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/fragment_success_existing.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/fragment_success_unset_existing.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/fragment_success_unset_non_existent.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/host_error_reserved.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/host_success_empty.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/host_success_encoded.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/host_success_existing.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/host_success_ip_future.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/host_success_ipv4.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/host_success_ipv6.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/host_success_new.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/host_success_unset_existing.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/host_success_unset_non_existent.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/path_error_reserved.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/path_error_unicode.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/path_error_without_leading_slash.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/path_success_email.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/path_success_empty.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/path_success_encoded.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/path_success_existing.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/port_error_negative.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/port_success_existing.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/port_success_new.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/port_success_unset_existing.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/port_success_unset_non_existent.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/query_error_reserved.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/query_error_unicode.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/query_success_context_sensitive_reserved.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/query_success_empty.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/query_success_encoded.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/query_success_existing.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/query_success_unset_existing.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/query_success_unset_non_existent.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/roundtrip_special_case1.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/roundtrip_special_case2.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/roundtrip_special_case3.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/scheme_error_empty.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/scheme_error_encoded.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/scheme_error_reserved.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/scheme_success_basic.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/scheme_success_unset_existing.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/scheme_success_unset_non_existent.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/userinfo_error_reserved.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/userinfo_success_empty.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/userinfo_success_encoded.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/userinfo_success_existing.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/userinfo_success_new.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/userinfo_success_unset_existing.phpt
create mode 100644 ext/uri/tests/rfc3986/modification/userinfo_success_unset_non_existent.phpt
create mode 100644 ext/uri/tests/whatwg/modification/fragment_success_auto_encode.phpt
create mode 100644 ext/uri/tests/whatwg/modification/fragment_success_empty.phpt
create mode 100644 ext/uri/tests/whatwg/modification/fragment_success_encoded.phpt
create mode 100644 ext/uri/tests/whatwg/modification/fragment_success_existing.phpt
create mode 100644 ext/uri/tests/whatwg/modification/fragment_success_hashmark.phpt
create mode 100644 ext/uri/tests/whatwg/modification/fragment_success_unicode.phpt
create mode 100644 ext/uri/tests/whatwg/modification/fragment_success_unset_existing.phpt
create mode 100644 ext/uri/tests/whatwg/modification/fragment_success_unset_non_existent.phpt
create mode 100644 ext/uri/tests/whatwg/modification/fragment_success_with_leading_hashmark.phpt
create mode 100644 ext/uri/tests/whatwg/modification/host_error_empty.phpt
create mode 100644 ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_opaque1.phpt
create mode 100644 ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_opaque2.phpt
create mode 100644 ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_opaque3.phpt
create mode 100644 ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_special1.phpt
create mode 100644 ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_special2.phpt
create mode 100644 ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_special3.phpt
create mode 100644 ext/uri/tests/whatwg/modification/host_error_unset_existing.phpt
create mode 100644 ext/uri/tests/whatwg/modification/host_success_encoded.phpt
create mode 100644 ext/uri/tests/whatwg/modification/host_success_existing.phpt
create mode 100644 ext/uri/tests/whatwg/modification/host_success_idna.phpt
create mode 100644 ext/uri/tests/whatwg/modification/host_success_ipv4.phpt
create mode 100644 ext/uri/tests/whatwg/modification/host_success_ipv6.phpt
create mode 100644 ext/uri/tests/whatwg/modification/password_success_auto_encoded.phpt
create mode 100644 ext/uri/tests/whatwg/modification/password_success_empty.phpt
create mode 100644 ext/uri/tests/whatwg/modification/password_success_encoded.phpt
create mode 100644 ext/uri/tests/whatwg/modification/password_success_existing.phpt
create mode 100644 ext/uri/tests/whatwg/modification/password_success_new.phpt
create mode 100644 ext/uri/tests/whatwg/modification/password_success_unset_existing.phpt
create mode 100644 ext/uri/tests/whatwg/modification/password_success_unset_non_existent1.phpt
create mode 100644 ext/uri/tests/whatwg/modification/password_success_unset_non_existent2.phpt
create mode 100644 ext/uri/tests/whatwg/modification/path_success_auto_encoded.phpt
create mode 100644 ext/uri/tests/whatwg/modification/path_success_empty.phpt
create mode 100644 ext/uri/tests/whatwg/modification/path_success_encoded.phpt
create mode 100644 ext/uri/tests/whatwg/modification/path_success_existing.phpt
create mode 100644 ext/uri/tests/whatwg/modification/path_success_unicode.phpt
create mode 100644 ext/uri/tests/whatwg/modification/path_success_without_leading_slash.phpt
create mode 100644 ext/uri/tests/whatwg/modification/port_error_negative.phpt
create mode 100644 ext/uri/tests/whatwg/modification/port_error_too_large.phpt
create mode 100644 ext/uri/tests/whatwg/modification/port_success_existing.phpt
create mode 100644 ext/uri/tests/whatwg/modification/port_success_new.phpt
create mode 100644 ext/uri/tests/whatwg/modification/port_success_special1.phpt
create mode 100644 ext/uri/tests/whatwg/modification/port_success_special2.phpt
create mode 100644 ext/uri/tests/whatwg/modification/port_success_unset_existing.phpt
create mode 100644 ext/uri/tests/whatwg/modification/port_success_unset_non_existent.phpt
create mode 100644 ext/uri/tests/whatwg/modification/query_success_auto_encoded.phpt
create mode 100644 ext/uri/tests/whatwg/modification/query_success_context_sensitive_reserved.phpt
create mode 100644 ext/uri/tests/whatwg/modification/query_success_empty.phpt
create mode 100644 ext/uri/tests/whatwg/modification/query_success_encoded.phpt
create mode 100644 ext/uri/tests/whatwg/modification/query_success_existing.phpt
create mode 100644 ext/uri/tests/whatwg/modification/query_success_question_mark.phpt
create mode 100644 ext/uri/tests/whatwg/modification/query_success_unicode.phpt
create mode 100644 ext/uri/tests/whatwg/modification/query_success_unset_existing.phpt
create mode 100644 ext/uri/tests/whatwg/modification/query_success_unset_non_existent.phpt
create mode 100644 ext/uri/tests/whatwg/modification/query_success_with_leading_question_mark.phpt
create mode 100644 ext/uri/tests/whatwg/modification/scheme_error_empty.phpt
create mode 100644 ext/uri/tests/whatwg/modification/scheme_error_encoded.phpt
create mode 100644 ext/uri/tests/whatwg/modification/scheme_error_invalid.phpt
create mode 100644 ext/uri/tests/whatwg/modification/scheme_success_basic.phpt
create mode 100644 ext/uri/tests/whatwg/modification/scheme_success_colon.phpt
create mode 100644 ext/uri/tests/whatwg/modification/scheme_success_full.phpt
create mode 100644 ext/uri/tests/whatwg/modification/username_success_auto_encoded.phpt
create mode 100644 ext/uri/tests/whatwg/modification/username_success_existing.phpt
create mode 100644 ext/uri/tests/whatwg/modification/username_success_new.phpt
create mode 100644 ext/uri/tests/whatwg/modification/username_success_unset_existing.phpt
create mode 100644 ext/uri/tests/whatwg/modification/username_success_unset_non_existent1.phpt
create mode 100644 ext/uri/tests/whatwg/modification/username_success_unset_non_existent2.phpt
diff --git a/ext/uri/tests/rfc3986/modification/fragment_error_reserved.phpt b/ext/uri/tests/rfc3986/modification/fragment_error_reserved.phpt
new file mode 100644
index 000000000000..4b3c3dd00a99
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/fragment_error_reserved.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - fragment - reserved characters
+--EXTENSIONS--
+uri
+--FILE--
+withFragment("#fragment");
+} catch (Uri\InvalidUriException $e) {
+ echo $e->getMessage() . "\n";
+}
+
+?>
+--EXPECT--
+The specified fragment is malformed
diff --git a/ext/uri/tests/rfc3986/modification/fragment_error_unicode.phpt b/ext/uri/tests/rfc3986/modification/fragment_error_unicode.phpt
new file mode 100644
index 000000000000..bbb1e2ffe872
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/fragment_error_unicode.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - fragment - unicode characters
+--EXTENSIONS--
+uri
+--FILE--
+withFragment("ő");
+} catch (Uri\InvalidUriException $e) {
+ echo $e->getMessage() . "\n";
+}
+
+?>
+--EXPECT--
+The specified fragment is malformed
diff --git a/ext/uri/tests/rfc3986/modification/fragment_success_empty.phpt b/ext/uri/tests/rfc3986/modification/fragment_success_empty.phpt
new file mode 100644
index 000000000000..f0a05d5bb5bb
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/fragment_success_empty.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - fragment - empty string
+--EXTENSIONS--
+uri
+--FILE--
+withFragment("");
+
+var_dump($uri1->getRawFragment());
+var_dump($uri2->getRawFragment());
+var_dump($uri2->toRawString());
+var_dump($uri2->getFragment());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+NULL
+string(0) ""
+string(20) "https://example.com#"
+string(0) ""
+string(20) "https://example.com#"
diff --git a/ext/uri/tests/rfc3986/modification/fragment_success_encoded.phpt b/ext/uri/tests/rfc3986/modification/fragment_success_encoded.phpt
new file mode 100644
index 000000000000..b1b1081ff81c
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/fragment_success_encoded.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - fragment - URL encoded characters
+--EXTENSIONS--
+uri
+--FILE--
+withFragment("foo%3db%61r"); // foo=bar
+
+var_dump($uri1->getRawFragment());
+var_dump($uri2->getRawFragment());
+var_dump($uri2->toRawString());
+var_dump($uri2->getFragment());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+NULL
+string(11) "foo%3db%61r"
+string(31) "https://example.com#foo%3db%61r"
+string(9) "foo%3Dbar"
+string(29) "https://example.com#foo%3Dbar"
diff --git a/ext/uri/tests/rfc3986/modification/fragment_success_existing.phpt b/ext/uri/tests/rfc3986/modification/fragment_success_existing.phpt
new file mode 100644
index 000000000000..fe534e846504
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/fragment_success_existing.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - fragment - changing an existing one
+--EXTENSIONS--
+uri
+--FILE--
+withFragment("bar");
+
+var_dump($uri1->getRawFragment());
+var_dump($uri2->getRawFragment());
+var_dump($uri2->toRawString());
+var_dump($uri2->getFragment());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+string(3) "foo"
+string(3) "bar"
+string(23) "https://example.com#bar"
+string(3) "bar"
+string(23) "https://example.com#bar"
diff --git a/ext/uri/tests/rfc3986/modification/fragment_success_unset_existing.phpt b/ext/uri/tests/rfc3986/modification/fragment_success_unset_existing.phpt
new file mode 100644
index 000000000000..7532c35e0fe7
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/fragment_success_unset_existing.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - fragment - unsetting existing
+--EXTENSIONS--
+uri
+--FILE--
+withFragment(null);
+
+var_dump($uri1->getRawFragment());
+var_dump($uri2->getRawFragment());
+var_dump($uri2->toRawString());
+var_dump($uri2->getFragment());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+string(3) "foo"
+NULL
+string(19) "https://example.com"
+NULL
+string(19) "https://example.com"
diff --git a/ext/uri/tests/rfc3986/modification/fragment_success_unset_non_existent.phpt b/ext/uri/tests/rfc3986/modification/fragment_success_unset_non_existent.phpt
new file mode 100644
index 000000000000..1c6fa898dde3
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/fragment_success_unset_non_existent.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - fragment - unsetting not-existent
+--EXTENSIONS--
+uri
+--FILE--
+withFragment(null);
+
+var_dump($uri1->getRawFragment());
+var_dump($uri2->getRawFragment());
+var_dump($uri2->toRawString());
+var_dump($uri2->getFragment());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+NULL
+NULL
+string(19) "https://example.com"
+NULL
+string(19) "https://example.com"
diff --git a/ext/uri/tests/rfc3986/modification/host_error_reserved.phpt b/ext/uri/tests/rfc3986/modification/host_error_reserved.phpt
new file mode 100644
index 000000000000..81d60bc2e400
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/host_error_reserved.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - host - reserved characters
+--EXTENSIONS--
+uri
+--FILE--
+withHost("ex#mple.com");
+} catch (Uri\InvalidUriException $e) {
+ echo $e->getMessage() . "\n";
+}
+
+?>
+--EXPECT--
+The specified host is malformed
diff --git a/ext/uri/tests/rfc3986/modification/host_success_empty.phpt b/ext/uri/tests/rfc3986/modification/host_success_empty.phpt
new file mode 100644
index 000000000000..b337674841c6
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/host_success_empty.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - host - empty string
+--EXTENSIONS--
+uri
+--FILE--
+withHost("");
+
+var_dump($uri1->getRawHost());
+var_dump($uri2->getRawHost());
+var_dump($uri2->toRawString());
+var_dump($uri2->getHost());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+string(11) "example.com"
+string(0) ""
+string(8) "https://"
+string(0) ""
+string(8) "https://"
diff --git a/ext/uri/tests/rfc3986/modification/host_success_encoded.phpt b/ext/uri/tests/rfc3986/modification/host_success_encoded.phpt
new file mode 100644
index 000000000000..d9db6003b157
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/host_success_encoded.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - host - URL encoded characters
+--EXTENSIONS--
+uri
+--FILE--
+withHost("%65xample.net"); // example.net
+
+var_dump($uri1->getRawHost());
+var_dump($uri2->getRawHost());
+var_dump($uri2->toRawString());
+var_dump($uri2->getHost());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+string(11) "example.com"
+string(13) "%65xample.net"
+string(21) "https://%65xample.net"
+string(11) "example.net"
+string(19) "https://example.net"
diff --git a/ext/uri/tests/rfc3986/modification/host_success_existing.phpt b/ext/uri/tests/rfc3986/modification/host_success_existing.phpt
new file mode 100644
index 000000000000..f9d3da987abc
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/host_success_existing.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - host - changing an existing one
+--EXTENSIONS--
+uri
+--FILE--
+withHost("example.net");
+
+var_dump($uri1->getRawHost());
+var_dump($uri2->getRawHost());
+var_dump($uri2->toRawString());
+var_dump($uri2->getHost());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+string(11) "example.com"
+string(11) "example.net"
+string(19) "https://example.net"
+string(11) "example.net"
+string(19) "https://example.net"
diff --git a/ext/uri/tests/rfc3986/modification/host_success_ip_future.phpt b/ext/uri/tests/rfc3986/modification/host_success_ip_future.phpt
new file mode 100644
index 000000000000..004210000cf4
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/host_success_ip_future.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - host - IP future address
+--EXTENSIONS--
+uri
+--FILE--
+withHost("[vF.addr]");
+
+var_dump($uri1->getRawHost());
+var_dump($uri2->getRawHost());
+var_dump($uri2->toRawString());
+var_dump($uri2->getHost());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+string(11) "example.com"
+string(9) "[vF.addr]"
+string(17) "https://[vF.addr]"
+string(9) "[vf.addr]"
+string(17) "https://[vf.addr]"
diff --git a/ext/uri/tests/rfc3986/modification/host_success_ipv4.phpt b/ext/uri/tests/rfc3986/modification/host_success_ipv4.phpt
new file mode 100644
index 000000000000..850a32281aba
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/host_success_ipv4.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - host - IPv4 address
+--EXTENSIONS--
+uri
+--FILE--
+withHost("192.168.0.1");
+
+var_dump($uri1->getRawHost());
+var_dump($uri2->getRawHost());
+var_dump($uri2->toRawString());
+var_dump($uri2->getHost());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+string(11) "example.com"
+string(11) "192.168.0.1"
+string(19) "https://192.168.0.1"
+string(11) "192.168.0.1"
+string(19) "https://192.168.0.1"
diff --git a/ext/uri/tests/rfc3986/modification/host_success_ipv6.phpt b/ext/uri/tests/rfc3986/modification/host_success_ipv6.phpt
new file mode 100644
index 000000000000..475088840159
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/host_success_ipv6.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - host - IPv6 address
+--EXTENSIONS--
+uri
+--FILE--
+withHost("[2001:0db8:3333:4444:5555:6666:7777:8888]");
+
+var_dump($uri1->getRawHost());
+var_dump($uri2->getRawHost());
+var_dump($uri2->toRawString());
+var_dump($uri2->getHost());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+string(11) "example.com"
+string(41) "[2001:0db8:3333:4444:5555:6666:7777:8888]"
+string(49) "https://[2001:0db8:3333:4444:5555:6666:7777:8888]"
+string(41) "[2001:0db8:3333:4444:5555:6666:7777:8888]"
+string(49) "https://[2001:0db8:3333:4444:5555:6666:7777:8888]"
diff --git a/ext/uri/tests/rfc3986/modification/host_success_new.phpt b/ext/uri/tests/rfc3986/modification/host_success_new.phpt
new file mode 100644
index 000000000000..326616140078
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/host_success_new.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - host - adding a new one
+--EXTENSIONS--
+uri
+--FILE--
+withHost("example.com");
+
+var_dump($uri1->getRawHost());
+var_dump($uri2->getRawHost());
+var_dump($uri2->toRawString());
+var_dump($uri2->getHost());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+NULL
+string(11) "example.com"
+string(21) "//example.com/foo/bar"
+string(11) "example.com"
+string(21) "//example.com/foo/bar"
diff --git a/ext/uri/tests/rfc3986/modification/host_success_unset_existing.phpt b/ext/uri/tests/rfc3986/modification/host_success_unset_existing.phpt
new file mode 100644
index 000000000000..521b6397ec45
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/host_success_unset_existing.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - host - unsetting existing
+--EXTENSIONS--
+uri
+--FILE--
+withHost(null);
+
+var_dump($uri1->getRawHost());
+var_dump($uri2->getRawHost());
+var_dump($uri2->toRawString());
+var_dump($uri2->getHost());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+string(11) "example.com"
+NULL
+string(7) "https:/"
+NULL
+string(7) "https:/"
diff --git a/ext/uri/tests/rfc3986/modification/host_success_unset_non_existent.phpt b/ext/uri/tests/rfc3986/modification/host_success_unset_non_existent.phpt
new file mode 100644
index 000000000000..b1793a31413a
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/host_success_unset_non_existent.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - host - unsetting non-existent
+--EXTENSIONS--
+uri
+--FILE--
+withHost(null);
+
+var_dump($uri1->getRawHost());
+var_dump($uri2->getRawHost());
+var_dump($uri2->toRawString());
+var_dump($uri2->getHost());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+NULL
+NULL
+string(8) "/foo/bar"
+NULL
+string(8) "/foo/bar"
diff --git a/ext/uri/tests/rfc3986/modification/path_error_reserved.phpt b/ext/uri/tests/rfc3986/modification/path_error_reserved.phpt
new file mode 100644
index 000000000000..2da84e2689b3
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/path_error_reserved.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - path - reserved characters
+--EXTENSIONS--
+uri
+--FILE--
+withPath("/[foo]");
+} catch (Uri\InvalidUriException $e) {
+ echo $e->getMessage() . "\n";
+}
+
+?>
+--EXPECT--
+The specified path is malformed
diff --git a/ext/uri/tests/rfc3986/modification/path_error_unicode.phpt b/ext/uri/tests/rfc3986/modification/path_error_unicode.phpt
new file mode 100644
index 000000000000..9335132dad56
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/path_error_unicode.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - path - unicode characters
+--EXTENSIONS--
+uri
+--FILE--
+withPath("/ő");
+} catch (Uri\InvalidUriException $e) {
+ echo $e->getMessage() . "\n";
+}
+
+?>
+--EXPECT--
+The specified path is malformed
diff --git a/ext/uri/tests/rfc3986/modification/path_error_without_leading_slash.phpt b/ext/uri/tests/rfc3986/modification/path_error_without_leading_slash.phpt
new file mode 100644
index 000000000000..476e4ec873c2
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/path_error_without_leading_slash.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - path - without leading slash
+--EXTENSIONS--
+uri
+--FILE--
+withPath("foo");
+} catch (Uri\InvalidUriException $e) {
+ echo $e->getMessage() . "\n";
+}
+
+?>
+--EXPECT--
+The specified path is malformed
diff --git a/ext/uri/tests/rfc3986/modification/path_success_email.phpt b/ext/uri/tests/rfc3986/modification/path_success_email.phpt
new file mode 100644
index 000000000000..58f5ab4baa6d
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/path_success_email.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - path - using an email format
+--EXTENSIONS--
+uri
+--FILE--
+withPath("john.doe@example.com");
+
+var_dump($uri1->getRawPath());
+var_dump($uri2->getRawPath());
+var_dump($uri2->toRawString());
+var_dump($uri2->getPath());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+string(0) ""
+string(20) "john.doe@example.com"
+string(20) "john.doe@example.com"
+string(20) "john.doe@example.com"
+string(20) "john.doe@example.com"
diff --git a/ext/uri/tests/rfc3986/modification/path_success_empty.phpt b/ext/uri/tests/rfc3986/modification/path_success_empty.phpt
new file mode 100644
index 000000000000..a67eeae44eed
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/path_success_empty.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - path - empty string
+--EXTENSIONS--
+uri
+--FILE--
+withPath("");
+
+var_dump($uri1->getRawPath());
+var_dump($uri2->getRawPath());
+var_dump($uri2->toRawString());
+var_dump($uri2->getPath());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+string(0) ""
+string(0) ""
+string(19) "https://example.com"
+string(0) ""
+string(19) "https://example.com"
diff --git a/ext/uri/tests/rfc3986/modification/path_success_encoded.phpt b/ext/uri/tests/rfc3986/modification/path_success_encoded.phpt
new file mode 100644
index 000000000000..05b62cafe250
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/path_success_encoded.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - path - URL encoded characters
+--EXTENSIONS--
+uri
+--FILE--
+withPath("/foo%2Fb%61r"); // /foo/bar
+
+var_dump($uri1->getRawPath());
+var_dump($uri2->getRawPath());
+var_dump($uri2->toRawString());
+var_dump($uri2->getPath());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+string(0) ""
+string(12) "/foo%2Fb%61r"
+string(31) "https://example.com/foo%2Fb%61r"
+string(10) "/foo%2Fbar"
+string(29) "https://example.com/foo%2Fbar"
diff --git a/ext/uri/tests/rfc3986/modification/path_success_existing.phpt b/ext/uri/tests/rfc3986/modification/path_success_existing.phpt
new file mode 100644
index 000000000000..6dafbc0a3ff8
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/path_success_existing.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - path - changing an existing one
+--EXTENSIONS--
+uri
+--FILE--
+withPath("/baz");
+
+var_dump($uri1->getRawPath());
+var_dump($uri2->getRawPath());
+var_dump($uri2->toRawString());
+var_dump($uri2->getPath());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+string(8) "/foo/bar"
+string(4) "/baz"
+string(23) "https://example.com/baz"
+string(4) "/baz"
+string(23) "https://example.com/baz"
diff --git a/ext/uri/tests/rfc3986/modification/port_error_negative.phpt b/ext/uri/tests/rfc3986/modification/port_error_negative.phpt
new file mode 100644
index 000000000000..598475b1e184
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/port_error_negative.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - host - too small number
+--EXTENSIONS--
+uri
+--FILE--
+withPort(-1);
+} catch (Uri\InvalidUriException $e) {
+ echo $e->getMessage() . "\n";
+}
+
+?>
+--EXPECT--
+The specified port is malformed
diff --git a/ext/uri/tests/rfc3986/modification/port_success_existing.phpt b/ext/uri/tests/rfc3986/modification/port_success_existing.phpt
new file mode 100644
index 000000000000..8451f1bcf469
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/port_success_existing.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - port - changing an existing one
+--EXTENSIONS--
+uri
+--FILE--
+withPort(443);
+
+var_dump($uri1->getPort());
+var_dump($uri2->getPort());
+var_dump($uri2->toRawString());
+
+?>
+--EXPECT--
+int(80)
+int(443)
+string(23) "https://example.com:443"
diff --git a/ext/uri/tests/rfc3986/modification/port_success_new.phpt b/ext/uri/tests/rfc3986/modification/port_success_new.phpt
new file mode 100644
index 000000000000..36ccea04a949
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/port_success_new.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - port - adding a new one
+--EXTENSIONS--
+uri
+--FILE--
+withPort(443);
+
+var_dump($uri1->getPort());
+var_dump($uri2->getPort());
+var_dump($uri2->toRawString());
+
+?>
+--EXPECT--
+NULL
+int(443)
+string(23) "https://example.com:443"
diff --git a/ext/uri/tests/rfc3986/modification/port_success_unset_existing.phpt b/ext/uri/tests/rfc3986/modification/port_success_unset_existing.phpt
new file mode 100644
index 000000000000..574af3f6e3ee
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/port_success_unset_existing.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - port - unsetting existing
+--EXTENSIONS--
+uri
+--FILE--
+withPort(null);
+
+var_dump($uri1->getPort());
+var_dump($uri2->getPort());
+var_dump($uri2->toRawString());
+
+?>
+--EXPECT--
+int(80)
+NULL
+string(19) "https://example.com"
diff --git a/ext/uri/tests/rfc3986/modification/port_success_unset_non_existent.phpt b/ext/uri/tests/rfc3986/modification/port_success_unset_non_existent.phpt
new file mode 100644
index 000000000000..a3fbdc5e8742
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/port_success_unset_non_existent.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - port - unsetting non-existent
+--EXTENSIONS--
+uri
+--FILE--
+withPort(null);
+
+var_dump($uri2->getPort());
+var_dump($uri2->getPort());
+var_dump($uri2->toRawString());
+
+?>
+--EXPECT--
+NULL
+NULL
+string(17) "ftp://example.com"
diff --git a/ext/uri/tests/rfc3986/modification/query_error_reserved.phpt b/ext/uri/tests/rfc3986/modification/query_error_reserved.phpt
new file mode 100644
index 000000000000..f09e867a0210
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/query_error_reserved.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - query - reserved characters
+--EXTENSIONS--
+uri
+--FILE--
+withQuery("#foo");
+} catch (Uri\InvalidUriException $e) {
+ echo $e->getMessage() . "\n";
+}
+
+?>
+--EXPECT--
+The specified query is malformed
diff --git a/ext/uri/tests/rfc3986/modification/query_error_unicode.phpt b/ext/uri/tests/rfc3986/modification/query_error_unicode.phpt
new file mode 100644
index 000000000000..c8f510059742
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/query_error_unicode.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - query - unicode characters
+--EXTENSIONS--
+uri
+--FILE--
+withQuery("ő");
+} catch (Uri\InvalidUriException $e) {
+ echo $e->getMessage() . "\n";
+}
+
+?>
+--EXPECT--
+The specified query is malformed
diff --git a/ext/uri/tests/rfc3986/modification/query_success_context_sensitive_reserved.phpt b/ext/uri/tests/rfc3986/modification/query_success_context_sensitive_reserved.phpt
new file mode 100644
index 000000000000..d40a7f7e09ef
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/query_success_context_sensitive_reserved.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - query - context-sensitive reserved character
+--EXTENSIONS--
+uri
+--FILE--
+withQuery("?foo=bar");
+
+var_dump($uri1->getRawQuery());
+var_dump($uri2->getRawQuery());
+var_dump($uri2->toRawString());
+var_dump($uri2->getQuery());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+NULL
+string(8) "?foo=bar"
+string(28) "https://example.com??foo=bar"
+string(8) "?foo=bar"
+string(28) "https://example.com??foo=bar"
diff --git a/ext/uri/tests/rfc3986/modification/query_success_empty.phpt b/ext/uri/tests/rfc3986/modification/query_success_empty.phpt
new file mode 100644
index 000000000000..e668b44df9b3
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/query_success_empty.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - query - empty string
+--EXTENSIONS--
+uri
+--FILE--
+withQuery("");
+
+var_dump($uri1->getRawQuery());
+var_dump($uri2->getRawQuery());
+var_dump($uri2->toRawString());
+var_dump($uri2->getQuery());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+NULL
+string(0) ""
+string(20) "https://example.com?"
+string(0) ""
+string(20) "https://example.com?"
diff --git a/ext/uri/tests/rfc3986/modification/query_success_encoded.phpt b/ext/uri/tests/rfc3986/modification/query_success_encoded.phpt
new file mode 100644
index 000000000000..7fd9707220d8
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/query_success_encoded.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - query - URL encoded characters
+--EXTENSIONS--
+uri
+--FILE--
+withQuery("foo%3dbar"); // foo=bar
+
+var_dump($uri1->getRawQuery());
+var_dump($uri2->getRawQuery());
+var_dump($uri2->toRawString());
+var_dump($uri2->getQuery());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+NULL
+string(9) "foo%3dbar"
+string(29) "https://example.com?foo%3dbar"
+string(9) "foo%3Dbar"
+string(29) "https://example.com?foo%3Dbar"
diff --git a/ext/uri/tests/rfc3986/modification/query_success_existing.phpt b/ext/uri/tests/rfc3986/modification/query_success_existing.phpt
new file mode 100644
index 000000000000..b5af7feee250
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/query_success_existing.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - query - changing an existing one
+--EXTENSIONS--
+uri
+--FILE--
+withQuery("foo=bar&baz=qux");
+
+var_dump($uri1->getRawQuery());
+var_dump($uri2->getRawQuery());
+var_dump($uri2->toRawString());
+var_dump($uri2->getQuery());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+string(7) "foo=bar"
+string(15) "foo=bar&baz=qux"
+string(35) "https://example.com?foo=bar&baz=qux"
+string(15) "foo=bar&baz=qux"
+string(35) "https://example.com?foo=bar&baz=qux"
diff --git a/ext/uri/tests/rfc3986/modification/query_success_unset_existing.phpt b/ext/uri/tests/rfc3986/modification/query_success_unset_existing.phpt
new file mode 100644
index 000000000000..89d130eedc27
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/query_success_unset_existing.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - query - unsetting existing
+--EXTENSIONS--
+uri
+--FILE--
+withQuery(null);
+
+var_dump($uri1->getRawQuery());
+var_dump($uri2->getRawQuery());
+var_dump($uri2->toRawString());
+var_dump($uri2->getQuery());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+string(7) "foo=bar"
+NULL
+string(19) "https://example.com"
+NULL
+string(19) "https://example.com"
diff --git a/ext/uri/tests/rfc3986/modification/query_success_unset_non_existent.phpt b/ext/uri/tests/rfc3986/modification/query_success_unset_non_existent.phpt
new file mode 100644
index 000000000000..d9dfcd208310
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/query_success_unset_non_existent.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - query - unsetting not-existent
+--EXTENSIONS--
+uri
+--FILE--
+withQuery(null);
+
+var_dump($uri1->getRawQuery());
+var_dump($uri2->getRawQuery());
+var_dump($uri2->toRawString());
+var_dump($uri2->getQuery());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+NULL
+NULL
+string(19) "https://example.com"
+NULL
+string(19) "https://example.com"
diff --git a/ext/uri/tests/rfc3986/modification/roundtrip_special_case1.phpt b/ext/uri/tests/rfc3986/modification/roundtrip_special_case1.phpt
new file mode 100644
index 000000000000..4349764d4dd1
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/roundtrip_special_case1.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification when roundtripping is not guaranteed - case 1
+--EXTENSIONS--
+uri
+--FILE--
+withHost("host");
+$uri2 = $uri2->withHost(null);
+
+var_dump($uri1->getRawPath());
+var_dump($uri2->getRawPath());
+var_dump($uri2->toRawString());
+var_dump($uri2->getPath());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+string(5) "path1"
+string(6) "/path1"
+string(6) "/path1"
+string(6) "/path1"
+string(6) "/path1"
diff --git a/ext/uri/tests/rfc3986/modification/roundtrip_special_case2.phpt b/ext/uri/tests/rfc3986/modification/roundtrip_special_case2.phpt
new file mode 100644
index 000000000000..624abf2fc49c
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/roundtrip_special_case2.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification when roundtripping is not guaranteed - case 2
+--EXTENSIONS--
+uri
+--FILE--
+withScheme(null);
+$uri2 = $uri2->withScheme("scheme");
+
+var_dump($uri1->toRawString());
+var_dump($uri2->toRawString());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+string(13) "scheme:path1:"
+string(15) "scheme:./path1:"
+string(13) "scheme:path1:"
diff --git a/ext/uri/tests/rfc3986/modification/roundtrip_special_case3.phpt b/ext/uri/tests/rfc3986/modification/roundtrip_special_case3.phpt
new file mode 100644
index 000000000000..7d6e1e4d0489
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/roundtrip_special_case3.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification when roundtripping is not guaranteed - case 3
+--EXTENSIONS--
+uri
+--FILE--
+withHost(null);
+$uri2 = $uri2->withHost("host");
+
+var_dump($uri1->toRawString());
+var_dump($uri2->toRawString());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+string(12) "//host//path"
+string(14) "//host/.//path"
+string(12) "//host//path"
diff --git a/ext/uri/tests/rfc3986/modification/scheme_error_empty.phpt b/ext/uri/tests/rfc3986/modification/scheme_error_empty.phpt
new file mode 100644
index 000000000000..477be1d2331c
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/scheme_error_empty.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - scheme - empty string
+--EXTENSIONS--
+uri
+--FILE--
+withScheme("");
+} catch (Uri\InvalidUriException $e) {
+ echo $e->getMessage() . "\n";
+}
+
+?>
+--EXPECT--
+The specified scheme is malformed
diff --git a/ext/uri/tests/rfc3986/modification/scheme_error_encoded.phpt b/ext/uri/tests/rfc3986/modification/scheme_error_encoded.phpt
new file mode 100644
index 000000000000..683f46cc42a8
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/scheme_error_encoded.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - scheme - URL encoded characters
+--EXTENSIONS--
+uri
+--FILE--
+withScheme("http%73");
+} catch (Uri\InvalidUriException $e) {
+ echo $e->getMessage() . "\n";
+}
+
+?>
+--EXPECT--
+The specified scheme is malformed
diff --git a/ext/uri/tests/rfc3986/modification/scheme_error_reserved.phpt b/ext/uri/tests/rfc3986/modification/scheme_error_reserved.phpt
new file mode 100644
index 000000000000..dd3bcc02f83e
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/scheme_error_reserved.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - scheme - reserved characters
+--EXTENSIONS--
+uri
+--FILE--
+withScheme("https:");
+} catch (Uri\InvalidUriException $e) {
+ echo $e->getMessage() . "\n";
+}
+
+?>
+--EXPECT--
+The specified scheme is malformed
diff --git a/ext/uri/tests/rfc3986/modification/scheme_success_basic.phpt b/ext/uri/tests/rfc3986/modification/scheme_success_basic.phpt
new file mode 100644
index 000000000000..695cb9c7f1e4
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/scheme_success_basic.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - scheme - basic case
+--EXTENSIONS--
+uri
+--FILE--
+withScheme("HTTP");
+
+var_dump($uri1->getRawScheme());
+var_dump($uri2->getRawScheme());
+var_dump($uri2->toRawString());
+var_dump($uri2->getScheme());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+string(5) "https"
+string(4) "HTTP"
+string(18) "HTTP://example.com"
+string(4) "http"
+string(18) "http://example.com"
diff --git a/ext/uri/tests/rfc3986/modification/scheme_success_unset_existing.phpt b/ext/uri/tests/rfc3986/modification/scheme_success_unset_existing.phpt
new file mode 100644
index 000000000000..67d447e8810e
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/scheme_success_unset_existing.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - scheme - unsetting existing
+--EXTENSIONS--
+uri
+--FILE--
+withScheme(null);
+
+var_dump($uri1->getRawScheme());
+var_dump($uri2->getRawScheme());
+var_dump($uri2->toRawString());
+var_dump($uri2->getScheme());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+string(5) "https"
+NULL
+string(13) "//example.com"
+NULL
+string(13) "//example.com"
diff --git a/ext/uri/tests/rfc3986/modification/scheme_success_unset_non_existent.phpt b/ext/uri/tests/rfc3986/modification/scheme_success_unset_non_existent.phpt
new file mode 100644
index 000000000000..4aa9b2d9dd2c
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/scheme_success_unset_non_existent.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - scheme - unsetting non-existent
+--EXTENSIONS--
+uri
+--FILE--
+withScheme(null);
+
+var_dump($uri1->getRawScheme());
+var_dump($uri2->getRawScheme());
+var_dump($uri2->toRawString());
+var_dump($uri2->getScheme());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+NULL
+NULL
+string(8) "/foo/bar"
+NULL
+string(8) "/foo/bar"
diff --git a/ext/uri/tests/rfc3986/modification/userinfo_error_reserved.phpt b/ext/uri/tests/rfc3986/modification/userinfo_error_reserved.phpt
new file mode 100644
index 000000000000..a5f820b0d59f
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/userinfo_error_reserved.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - userinfo - reserved characters
+--EXTENSIONS--
+uri
+--FILE--
+withUserInfo("us/r:password"); // us/r:password
+} catch (Uri\InvalidUriException $e) {
+ echo $e->getMessage() . "\n";
+}
+
+?>
+--EXPECT--
+The specified userinfo is malformed
diff --git a/ext/uri/tests/rfc3986/modification/userinfo_success_empty.phpt b/ext/uri/tests/rfc3986/modification/userinfo_success_empty.phpt
new file mode 100644
index 000000000000..ab753e6de507
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/userinfo_success_empty.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - userinfo - empty string
+--EXTENSIONS--
+uri
+--FILE--
+withUserInfo("");
+
+var_dump($uri1->getRawUserInfo());
+var_dump($uri2->getRawUserInfo());
+var_dump($uri2->getUserInfo());
+
+?>
+--EXPECT--
+NULL
+string(0) ""
+string(0) ""
diff --git a/ext/uri/tests/rfc3986/modification/userinfo_success_encoded.phpt b/ext/uri/tests/rfc3986/modification/userinfo_success_encoded.phpt
new file mode 100644
index 000000000000..a4b7409d6706
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/userinfo_success_encoded.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - userinfo - URL encoded characters
+--EXTENSIONS--
+uri
+--FILE--
+withUserInfo("%75s%2Fr:password"); // us/r:password
+
+var_dump($uri1->getRawUserInfo());
+var_dump($uri2->getRawUserInfo());
+var_dump($uri2->toRawString());
+var_dump($uri2->getUserInfo());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+NULL
+string(17) "%75s%2Fr:password"
+string(37) "https://%75s%2Fr:password@example.com"
+string(15) "us%2Fr:password"
+string(35) "https://us%2Fr:password@example.com"
diff --git a/ext/uri/tests/rfc3986/modification/userinfo_success_existing.phpt b/ext/uri/tests/rfc3986/modification/userinfo_success_existing.phpt
new file mode 100644
index 000000000000..a13e091075cb
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/userinfo_success_existing.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - userinfo - changing an existing one
+--EXTENSIONS--
+uri
+--FILE--
+withUserInfo("user:password");
+
+var_dump($uri1->getRawUserInfo());
+var_dump($uri2->getRawUserInfo());
+var_dump($uri2->toRawString());
+var_dump($uri2->getUserInfo());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+string(5) ":pass"
+string(13) "user:password"
+string(33) "https://user:password@example.com"
+string(13) "user:password"
+string(33) "https://user:password@example.com"
diff --git a/ext/uri/tests/rfc3986/modification/userinfo_success_new.phpt b/ext/uri/tests/rfc3986/modification/userinfo_success_new.phpt
new file mode 100644
index 000000000000..dc49c10d7526
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/userinfo_success_new.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - userinfo - adding a new one
+--EXTENSIONS--
+uri
+--FILE--
+withUserInfo("user:password");
+
+var_dump($uri1->getRawUserInfo());
+var_dump($uri2->getRawUserInfo());
+var_dump($uri2->toRawString());
+var_dump($uri2->getUserInfo());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+NULL
+string(13) "user:password"
+string(33) "https://user:password@example.com"
+string(13) "user:password"
+string(33) "https://user:password@example.com"
diff --git a/ext/uri/tests/rfc3986/modification/userinfo_success_unset_existing.phpt b/ext/uri/tests/rfc3986/modification/userinfo_success_unset_existing.phpt
new file mode 100644
index 000000000000..0f4e7219cbd3
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/userinfo_success_unset_existing.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - userinfo - unsetting existing
+--EXTENSIONS--
+uri
+--FILE--
+withUserInfo(null);
+
+var_dump($uri1->getRawUserInfo());
+var_dump($uri2->getRawUserInfo());
+var_dump($uri2->toRawString());
+var_dump($uri2->getUserInfo());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+string(13) "user:password"
+NULL
+string(19) "https://example.com"
+NULL
+string(19) "https://example.com"
diff --git a/ext/uri/tests/rfc3986/modification/userinfo_success_unset_non_existent.phpt b/ext/uri/tests/rfc3986/modification/userinfo_success_unset_non_existent.phpt
new file mode 100644
index 000000000000..9aa2a5999ac4
--- /dev/null
+++ b/ext/uri/tests/rfc3986/modification/userinfo_success_unset_non_existent.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\Rfc3986\Uri component modification - userinfo - unsetting non-existent
+--EXTENSIONS--
+uri
+--FILE--
+withUserInfo(null);
+
+var_dump($uri1->getRawUserInfo());
+var_dump($uri2->getRawUserInfo());
+var_dump($uri2->toRawString());
+var_dump($uri2->getUserInfo());
+var_dump($uri2->toString());
+
+?>
+--EXPECT--
+NULL
+NULL
+string(8) "/foo/bar"
+NULL
+string(8) "/foo/bar"
diff --git a/ext/uri/tests/whatwg/modification/fragment_success_auto_encode.phpt b/ext/uri/tests/whatwg/modification/fragment_success_auto_encode.phpt
new file mode 100644
index 000000000000..ac74b8668cd2
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/fragment_success_auto_encode.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - fragment - characters from the percent encode set
+--EXTENSIONS--
+uri
+--FILE--
+withFragment("<>");
+
+var_dump($url1->getFragment());
+var_dump($url2->getFragment());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+NULL
+string(6) "%3C%3E"
+string(27) "https://example.com/#%3C%3E"
diff --git a/ext/uri/tests/whatwg/modification/fragment_success_empty.phpt b/ext/uri/tests/whatwg/modification/fragment_success_empty.phpt
new file mode 100644
index 000000000000..5b3aa9426232
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/fragment_success_empty.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - fragment - empty string
+--EXTENSIONS--
+uri
+--FILE--
+withFragment("");
+
+var_dump($url1->getFragment());
+var_dump($url2->getFragment());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+NULL
+NULL
+string(20) "https://example.com/"
diff --git a/ext/uri/tests/whatwg/modification/fragment_success_encoded.phpt b/ext/uri/tests/whatwg/modification/fragment_success_encoded.phpt
new file mode 100644
index 000000000000..9473ea9535f9
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/fragment_success_encoded.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - fragment - URL encoded characters
+--EXTENSIONS--
+uri
+--FILE--
+withFragment("foo%3db%61r"); // foo=bar
+
+var_dump($url1->getFragment());
+var_dump($url2->getFragment());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+NULL
+string(11) "foo%3db%61r"
+string(32) "https://example.com/#foo%3db%61r"
diff --git a/ext/uri/tests/whatwg/modification/fragment_success_existing.phpt b/ext/uri/tests/whatwg/modification/fragment_success_existing.phpt
new file mode 100644
index 000000000000..0a7d253434d4
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/fragment_success_existing.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - fragment - changing an existing one
+--EXTENSIONS--
+uri
+--FILE--
+withFragment("bar");
+
+var_dump($url1->getFragment());
+var_dump($url2->getFragment());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+string(3) "foo"
+string(3) "bar"
+string(24) "https://example.com/#bar"
diff --git a/ext/uri/tests/whatwg/modification/fragment_success_hashmark.phpt b/ext/uri/tests/whatwg/modification/fragment_success_hashmark.phpt
new file mode 100644
index 000000000000..12ce6d6e6b64
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/fragment_success_hashmark.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - fragment - only a hashmark character
+--EXTENSIONS--
+uri
+--FILE--
+withFragment("#");
+
+var_dump($url1->getFragment());
+var_dump($url2->getFragment());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+NULL
+NULL
+string(21) "https://example.com/#"
diff --git a/ext/uri/tests/whatwg/modification/fragment_success_unicode.phpt b/ext/uri/tests/whatwg/modification/fragment_success_unicode.phpt
new file mode 100644
index 000000000000..c609b5df042d
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/fragment_success_unicode.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - fragment - unicode characters
+--EXTENSIONS--
+uri
+--FILE--
+withFragment("ő");
+
+var_dump($url1->getFragment());
+var_dump($url2->getFragment());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+NULL
+string(6) "%C5%91"
+string(27) "https://example.com/#%C5%91"
diff --git a/ext/uri/tests/whatwg/modification/fragment_success_unset_existing.phpt b/ext/uri/tests/whatwg/modification/fragment_success_unset_existing.phpt
new file mode 100644
index 000000000000..585707e497e5
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/fragment_success_unset_existing.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - fragment - unsetting existing
+--EXTENSIONS--
+uri
+--FILE--
+withFragment(null);
+
+var_dump($url1->getFragment());
+var_dump($url2->getFragment());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+string(3) "foo"
+NULL
+string(20) "https://example.com/"
diff --git a/ext/uri/tests/whatwg/modification/fragment_success_unset_non_existent.phpt b/ext/uri/tests/whatwg/modification/fragment_success_unset_non_existent.phpt
new file mode 100644
index 000000000000..21e295db23ec
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/fragment_success_unset_non_existent.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - fragment - unsetting not-existent
+--EXTENSIONS--
+uri
+--FILE--
+withFragment(null);
+
+var_dump($url1->getFragment());
+var_dump($url2->getFragment());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+NULL
+NULL
+string(20) "https://example.com/"
diff --git a/ext/uri/tests/whatwg/modification/fragment_success_with_leading_hashmark.phpt b/ext/uri/tests/whatwg/modification/fragment_success_with_leading_hashmark.phpt
new file mode 100644
index 000000000000..4523388223b6
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/fragment_success_with_leading_hashmark.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - fragment - with leading hashmark
+--EXTENSIONS--
+uri
+--FILE--
+withFragment("#fragment");
+
+var_dump($url1->getFragment());
+var_dump($url2->getFragment());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+NULL
+string(8) "fragment"
+string(29) "https://example.com/#fragment"
diff --git a/ext/uri/tests/whatwg/modification/host_error_empty.phpt b/ext/uri/tests/whatwg/modification/host_error_empty.phpt
new file mode 100644
index 000000000000..f9f473957860
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/host_error_empty.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - host - empty string
+--EXTENSIONS--
+uri
+--FILE--
+withHost("");
+} catch (Uri\WhatWg\InvalidUrlException $e) {
+ echo $e->getMessage() . "\n";
+}
+
+?>
+--EXPECT--
+The specified host is malformed (HostMissing)
diff --git a/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_opaque1.phpt b/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_opaque1.phpt
new file mode 100644
index 000000000000..8aebc5f7057d
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_opaque1.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - host - forbidden host code point
+--EXTENSIONS--
+uri
+--FILE--
+withHost("ex@mple.com");
+} catch (Uri\WhatWg\InvalidUrlException $e) {
+ echo $e->getMessage() . "\n";
+}
+
+?>
+--EXPECT--
+The specified host is malformed (HostInvalidCodePoint)
diff --git a/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_opaque2.phpt b/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_opaque2.phpt
new file mode 100644
index 000000000000..6d8b0c8b6565
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_opaque2.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - host - forbidden host code point
+--EXTENSIONS--
+uri
+--FILE--
+withHost("ex#mple.com");
+
+var_dump($url1->getAsciiHost());
+var_dump($url2->getAsciiHost());
+
+?>
+--EXPECT--
+string(11) "example.com"
+string(2) "ex"
diff --git a/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_opaque3.phpt b/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_opaque3.phpt
new file mode 100644
index 000000000000..7d32dcba2c6c
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_opaque3.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - host - forbidden host codepoint
+--EXTENSIONS--
+uri
+--FILE--
+withHost("ex#mple.com");
+
+var_dump($url1->getAsciiHost());
+var_dump($url2->getAsciiHost());
+
+?>
+--EXPECT--
+string(11) "example.com"
+string(2) "ex"
diff --git a/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_special1.phpt b/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_special1.phpt
new file mode 100644
index 000000000000..a27c26381b4e
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_special1.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - host - forbidden domain code point
+--EXTENSIONS--
+uri
+--FILE--
+withHost("ex@mple.com");
+} catch (Uri\WhatWg\InvalidUrlException $e) {
+ echo $e->getMessage() . "\n";
+}
+
+?>
+--EXPECT--
+The specified host is malformed (DomainInvalidCodePoint)
diff --git a/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_special2.phpt b/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_special2.phpt
new file mode 100644
index 000000000000..a0626d99c51a
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_special2.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - host - forbidden domain code point
+--EXTENSIONS--
+uri
+--FILE--
+withHost("ex:mple.com");
+} catch (Uri\WhatWg\InvalidUrlException $e) {
+ echo $e->getMessage() . "\n";
+}
+
+?>
+--EXPECT--
+The specified host is malformed
diff --git a/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_special3.phpt b/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_special3.phpt
new file mode 100644
index 000000000000..a0626d99c51a
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/host_error_forbidden_host_codepoint_special3.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - host - forbidden domain code point
+--EXTENSIONS--
+uri
+--FILE--
+withHost("ex:mple.com");
+} catch (Uri\WhatWg\InvalidUrlException $e) {
+ echo $e->getMessage() . "\n";
+}
+
+?>
+--EXPECT--
+The specified host is malformed
diff --git a/ext/uri/tests/whatwg/modification/host_error_unset_existing.phpt b/ext/uri/tests/whatwg/modification/host_error_unset_existing.phpt
new file mode 100644
index 000000000000..ca5d5a0201d7
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/host_error_unset_existing.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - host - unsetting existing
+--EXTENSIONS--
+uri
+--FILE--
+withHost(null);
+} catch (Uri\WhatWg\InvalidUrlException $e) {
+ echo $e->getMessage() . "\n";
+}
+
+?>
+--EXPECT--
+The specified host is malformed (HostMissing)
diff --git a/ext/uri/tests/whatwg/modification/host_success_encoded.phpt b/ext/uri/tests/whatwg/modification/host_success_encoded.phpt
new file mode 100644
index 000000000000..9604476554fc
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/host_success_encoded.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - host - URL encoded characters
+--EXTENSIONS--
+uri
+--FILE--
+withHost("%65xample.net"); // example.net
+
+var_dump($url1->getAsciiHost());
+var_dump($url2->getAsciiHost());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+string(11) "example.com"
+string(11) "example.net"
+string(20) "https://example.net/"
diff --git a/ext/uri/tests/whatwg/modification/host_success_existing.phpt b/ext/uri/tests/whatwg/modification/host_success_existing.phpt
new file mode 100644
index 000000000000..57394c851c77
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/host_success_existing.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - host - changing an existing one
+--EXTENSIONS--
+uri
+--FILE--
+withHost("example.net");
+
+var_dump($url1->getAsciiHost());
+var_dump($url2->getAsciiHost());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+string(11) "example.com"
+string(11) "example.net"
+string(20) "https://example.net/"
diff --git a/ext/uri/tests/whatwg/modification/host_success_idna.phpt b/ext/uri/tests/whatwg/modification/host_success_idna.phpt
new file mode 100644
index 000000000000..919e22934dfa
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/host_success_idna.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - host - IDNA characters
+--EXTENSIONS--
+uri
+--FILE--
+withHost("éxämple.com");
+
+var_dump($url1->getAsciiHost());
+var_dump($url2->getAsciiHost());
+var_dump($url2->toAsciiString());
+var_dump($url2->getUnicodeHost());
+var_dump($url2->toUnicodeString());
+
+?>
+--EXPECT--
+string(11) "example.com"
+string(19) "xn--xmple-gra7a.com"
+string(28) "https://xn--xmple-gra7a.com/"
+string(13) "éxämple.com"
+string(22) "https://éxämple.com/"
diff --git a/ext/uri/tests/whatwg/modification/host_success_ipv4.phpt b/ext/uri/tests/whatwg/modification/host_success_ipv4.phpt
new file mode 100644
index 000000000000..fef9e0fc6376
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/host_success_ipv4.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - host - IPv4 address
+--EXTENSIONS--
+uri
+--FILE--
+withHost("192.168.0.1");
+
+var_dump($url1->getAsciiHost());
+var_dump($url2->getAsciiHost());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+string(11) "example.com"
+string(11) "192.168.0.1"
+string(20) "https://192.168.0.1/"
diff --git a/ext/uri/tests/whatwg/modification/host_success_ipv6.phpt b/ext/uri/tests/whatwg/modification/host_success_ipv6.phpt
new file mode 100644
index 000000000000..2124b70ef56d
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/host_success_ipv6.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - host - IPv6 address
+--EXTENSIONS--
+uri
+--FILE--
+withHost("[2001:0db8:3333:4444:5555:6666:7777:8888]");
+
+var_dump($url1->getAsciiHost());
+var_dump($url2->getAsciiHost());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+string(11) "example.com"
+string(40) "[2001:db8:3333:4444:5555:6666:7777:8888]"
+string(49) "https://[2001:db8:3333:4444:5555:6666:7777:8888]/"
diff --git a/ext/uri/tests/whatwg/modification/password_success_auto_encoded.phpt b/ext/uri/tests/whatwg/modification/password_success_auto_encoded.phpt
new file mode 100644
index 000000000000..5db68cb90a62
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/password_success_auto_encoded.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - password - characters from the percent encode set
+--EXTENSIONS--
+uri
+--FILE--
+withPassword("p:s/");
+
+var_dump($url1->getPassword());
+var_dump($url2->getPassword());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+string(8) "password"
+string(8) "p%3As%2F"
+string(34) "https://user:p%3As%2F@example.com/"
diff --git a/ext/uri/tests/whatwg/modification/password_success_empty.phpt b/ext/uri/tests/whatwg/modification/password_success_empty.phpt
new file mode 100644
index 000000000000..40c350cc1b30
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/password_success_empty.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - password - empty string
+--EXTENSIONS--
+uri
+--FILE--
+withPassword("");
+
+var_dump($url1->getPassword());
+var_dump($url2->getPassword());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+NULL
+NULL
+string(20) "https://example.com/"
diff --git a/ext/uri/tests/whatwg/modification/password_success_encoded.phpt b/ext/uri/tests/whatwg/modification/password_success_encoded.phpt
new file mode 100644
index 000000000000..82b172d914af
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/password_success_encoded.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - password - URL encoded characters
+--EXTENSIONS--
+uri
+--FILE--
+withPassword("p%61ssword");
+
+var_dump($url1->getPassword());
+var_dump($url2->getPassword());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+NULL
+string(10) "p%61ssword"
+string(32) "https://:p%61ssword@example.com/"
diff --git a/ext/uri/tests/whatwg/modification/password_success_existing.phpt b/ext/uri/tests/whatwg/modification/password_success_existing.phpt
new file mode 100644
index 000000000000..61b0ce3909b4
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/password_success_existing.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - password - changing an existing one
+--EXTENSIONS--
+uri
+--FILE--
+withPassword("password");
+
+var_dump($url1->getPassword());
+var_dump($url2->getPassword());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+string(4) "pass"
+string(8) "password"
+string(30) "https://:password@example.com/"
diff --git a/ext/uri/tests/whatwg/modification/password_success_new.phpt b/ext/uri/tests/whatwg/modification/password_success_new.phpt
new file mode 100644
index 000000000000..8357b9972109
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/password_success_new.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - username - adding a new one
+--EXTENSIONS--
+uri
+--FILE--
+withPassword("password");
+
+var_dump($url1->getPassword());
+var_dump($url2->getPassword());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+NULL
+string(8) "password"
+string(30) "https://:password@example.com/"
diff --git a/ext/uri/tests/whatwg/modification/password_success_unset_existing.phpt b/ext/uri/tests/whatwg/modification/password_success_unset_existing.phpt
new file mode 100644
index 000000000000..957973b062a2
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/password_success_unset_existing.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - password - unsetting existing
+--EXTENSIONS--
+uri
+--FILE--
+withPassword(null);
+
+var_dump($url1->getPassword());
+var_dump($url2->getPassword());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+string(8) "password"
+NULL
+string(29) "https://username@example.com/"
diff --git a/ext/uri/tests/whatwg/modification/password_success_unset_non_existent1.phpt b/ext/uri/tests/whatwg/modification/password_success_unset_non_existent1.phpt
new file mode 100644
index 000000000000..357b33b78c0b
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/password_success_unset_non_existent1.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - password - unsetting non-existent
+--EXTENSIONS--
+uri
+--FILE--
+withPassword(null);
+
+var_dump($url1->getPassword());
+var_dump($url2->getPassword());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+NULL
+NULL
+string(20) "https://example.com/"
diff --git a/ext/uri/tests/whatwg/modification/password_success_unset_non_existent2.phpt b/ext/uri/tests/whatwg/modification/password_success_unset_non_existent2.phpt
new file mode 100644
index 000000000000..a2140669ee8a
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/password_success_unset_non_existent2.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - username - unsetting non-existent
+--EXTENSIONS--
+uri
+--FILE--
+withPassword(null);
+
+var_dump($url1->getPassword());
+var_dump($url2->getPassword());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+NULL
+NULL
+string(29) "https://username@example.com/"
diff --git a/ext/uri/tests/whatwg/modification/path_success_auto_encoded.phpt b/ext/uri/tests/whatwg/modification/path_success_auto_encoded.phpt
new file mode 100644
index 000000000000..59f539124c68
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/path_success_auto_encoded.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - path - characters from the percent encode set
+--EXTENSIONS--
+uri
+--FILE--
+withPath("/p^th#");
+
+var_dump($url1->getPath());
+var_dump($url2->getPath());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+string(1) "/"
+string(8) "/p^th%23"
+string(27) "https://example.com/p^th%23"
diff --git a/ext/uri/tests/whatwg/modification/path_success_empty.phpt b/ext/uri/tests/whatwg/modification/path_success_empty.phpt
new file mode 100644
index 000000000000..9e8d3495445a
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/path_success_empty.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - path - empty string
+--EXTENSIONS--
+uri
+--FILE--
+withPath("");
+
+var_dump($url1->getPath());
+var_dump($url2->getPath());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+string(1) "/"
+string(1) "/"
+string(20) "https://example.com/"
diff --git a/ext/uri/tests/whatwg/modification/path_success_encoded.phpt b/ext/uri/tests/whatwg/modification/path_success_encoded.phpt
new file mode 100644
index 000000000000..b698c4691b0c
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/path_success_encoded.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - path - URL encoded characters
+--EXTENSIONS--
+uri
+--FILE--
+withPath("/foo%2Fb%61r"); // /foo/bar
+
+var_dump($url1->getPath());
+var_dump($url2->getPath());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+string(1) "/"
+string(12) "/foo%2Fb%61r"
+string(31) "https://example.com/foo%2Fb%61r"
diff --git a/ext/uri/tests/whatwg/modification/path_success_existing.phpt b/ext/uri/tests/whatwg/modification/path_success_existing.phpt
new file mode 100644
index 000000000000..113c8c88d48b
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/path_success_existing.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - path - changing an existing one
+--EXTENSIONS--
+uri
+--FILE--
+withPath("/baz");
+
+var_dump($url1->getPath());
+var_dump($url2->getPath());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+string(8) "/foo/bar"
+string(4) "/baz"
+string(23) "https://example.com/baz"
diff --git a/ext/uri/tests/whatwg/modification/path_success_unicode.phpt b/ext/uri/tests/whatwg/modification/path_success_unicode.phpt
new file mode 100644
index 000000000000..d195a6dadbc1
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/path_success_unicode.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - path - unicode characters
+--EXTENSIONS--
+uri
+--FILE--
+withPath("/ő");
+
+var_dump($url1->getPath());
+var_dump($url2->getPath());
+var_dump($url2->toAsciiString());
+?>
+--EXPECT--
+string(1) "/"
+string(7) "/%C5%91"
+string(26) "https://example.com/%C5%91"
diff --git a/ext/uri/tests/whatwg/modification/path_success_without_leading_slash.phpt b/ext/uri/tests/whatwg/modification/path_success_without_leading_slash.phpt
new file mode 100644
index 000000000000..1149287dc531
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/path_success_without_leading_slash.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - path - without leading slash
+--EXTENSIONS--
+uri
+--FILE--
+withPath("foo/bar");
+
+var_dump($url1->getPath());
+var_dump($url2->getPath());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+string(1) "/"
+string(8) "/foo/bar"
+string(27) "https://example.com/foo/bar"
diff --git a/ext/uri/tests/whatwg/modification/port_error_negative.phpt b/ext/uri/tests/whatwg/modification/port_error_negative.phpt
new file mode 100644
index 000000000000..5de87d7e7608
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/port_error_negative.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - port - negative number
+--EXTENSIONS--
+uri
+--FILE--
+withPort(-1);
+} catch (Uri\WhatWg\InvalidUrlException $e) {
+ echo $e->getMessage() . "\n";
+}
+
+?>
+--EXPECT--
+The specified port is malformed
diff --git a/ext/uri/tests/whatwg/modification/port_error_too_large.phpt b/ext/uri/tests/whatwg/modification/port_error_too_large.phpt
new file mode 100644
index 000000000000..4060056b0a56
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/port_error_too_large.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - host - larger than a 16-bit unsigned integer
+--EXTENSIONS--
+uri
+--FILE--
+withPort(65536);
+} catch (Uri\WhatWg\InvalidUrlException $e) {
+ echo $e->getMessage() . "\n";
+}
+
+?>
+--EXPECT--
+The specified port is malformed (PortOutOfRange)
diff --git a/ext/uri/tests/whatwg/modification/port_success_existing.phpt b/ext/uri/tests/whatwg/modification/port_success_existing.phpt
new file mode 100644
index 000000000000..e5ea806bd1a4
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/port_success_existing.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - port - changing an existing one
+--EXTENSIONS--
+uri
+--FILE--
+withPort(443);
+
+var_dump($url1->getPort());
+var_dump($url2->getPort());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+int(80)
+int(443)
+string(24) "scheme://example.com:443"
diff --git a/ext/uri/tests/whatwg/modification/port_success_new.phpt b/ext/uri/tests/whatwg/modification/port_success_new.phpt
new file mode 100644
index 000000000000..85098b21b7b3
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/port_success_new.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - port - adding a new one
+--EXTENSIONS--
+uri
+--FILE--
+withPort(443);
+
+var_dump($url1->getPort());
+var_dump($url2->getPort());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+NULL
+int(443)
+string(24) "scheme://example.com:443"
diff --git a/ext/uri/tests/whatwg/modification/port_success_special1.phpt b/ext/uri/tests/whatwg/modification/port_success_special1.phpt
new file mode 100644
index 000000000000..ba85449e4353
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/port_success_special1.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - port - adding a new one for a special URL
+--EXTENSIONS--
+uri
+--FILE--
+withPort(80);
+
+var_dump($url1->getPort());
+var_dump($url2->getPort());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+int(88)
+NULL
+string(19) "http://example.com/"
diff --git a/ext/uri/tests/whatwg/modification/port_success_special2.phpt b/ext/uri/tests/whatwg/modification/port_success_special2.phpt
new file mode 100644
index 000000000000..d9f0074f0532
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/port_success_special2.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - port - adding a new one for a special URL
+--EXTENSIONS--
+uri
+--FILE--
+withPort(443);
+
+var_dump($url1->getPort());
+var_dump($url2->getPort());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+NULL
+NULL
+string(20) "https://example.com/"
diff --git a/ext/uri/tests/whatwg/modification/port_success_unset_existing.phpt b/ext/uri/tests/whatwg/modification/port_success_unset_existing.phpt
new file mode 100644
index 000000000000..c280c181b19a
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/port_success_unset_existing.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - port - unsetting existing
+--EXTENSIONS--
+uri
+--FILE--
+withPort(null);
+
+var_dump($url1->getPort());
+var_dump($url2->getPort());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+int(80)
+NULL
+string(20) "https://example.com/"
diff --git a/ext/uri/tests/whatwg/modification/port_success_unset_non_existent.phpt b/ext/uri/tests/whatwg/modification/port_success_unset_non_existent.phpt
new file mode 100644
index 000000000000..d364c72d7002
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/port_success_unset_non_existent.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - port - unsetting non-existent
+--EXTENSIONS--
+uri
+--FILE--
+withPort(null);
+
+var_dump($url2->getPort());
+var_dump($url2->getPort());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+NULL
+NULL
+string(18) "ftp://example.com/"
diff --git a/ext/uri/tests/whatwg/modification/query_success_auto_encoded.phpt b/ext/uri/tests/whatwg/modification/query_success_auto_encoded.phpt
new file mode 100644
index 000000000000..fc487f33797d
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/query_success_auto_encoded.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - query - characters from the percent encode set
+--EXTENSIONS--
+uri
+--FILE--
+withQuery("#foo ");
+
+var_dump($url1->getQuery());
+var_dump($url2->getQuery());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+NULL
+string(9) "%23foo%20"
+string(30) "https://example.com/?%23foo%20"
diff --git a/ext/uri/tests/whatwg/modification/query_success_context_sensitive_reserved.phpt b/ext/uri/tests/whatwg/modification/query_success_context_sensitive_reserved.phpt
new file mode 100644
index 000000000000..cb220a0a33ef
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/query_success_context_sensitive_reserved.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - query - context-sensitive reserved character
+--EXTENSIONS--
+uri
+--FILE--
+withQuery("?foo=bar");
+
+var_dump($url1->getQuery());
+var_dump($url2->getQuery());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+NULL
+string(7) "foo=bar"
+string(28) "https://example.com/?foo=bar"
diff --git a/ext/uri/tests/whatwg/modification/query_success_empty.phpt b/ext/uri/tests/whatwg/modification/query_success_empty.phpt
new file mode 100644
index 000000000000..dcb98bc37689
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/query_success_empty.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - query - empty string
+--EXTENSIONS--
+uri
+--FILE--
+withQuery("");
+
+var_dump($url1->getQuery());
+var_dump($url2->getQuery());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+NULL
+NULL
+string(20) "https://example.com/"
diff --git a/ext/uri/tests/whatwg/modification/query_success_encoded.phpt b/ext/uri/tests/whatwg/modification/query_success_encoded.phpt
new file mode 100644
index 000000000000..f9935015f7bd
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/query_success_encoded.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - query - URL encoded characters
+--EXTENSIONS--
+uri
+--FILE--
+withQuery("foo%3db%61r"); // foo=bar
+
+var_dump($url1->getQuery());
+var_dump($url2->getQuery());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+NULL
+string(11) "foo%3db%61r"
+string(32) "https://example.com/?foo%3db%61r"
diff --git a/ext/uri/tests/whatwg/modification/query_success_existing.phpt b/ext/uri/tests/whatwg/modification/query_success_existing.phpt
new file mode 100644
index 000000000000..b3429b58b865
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/query_success_existing.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - query - changing an existing one
+--EXTENSIONS--
+uri
+--FILE--
+withQuery("foo=bar&baz=qux");
+
+var_dump($url1->getQuery());
+var_dump($url2->getQuery());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+string(7) "foo=bar"
+string(15) "foo=bar&baz=qux"
+string(36) "https://example.com/?foo=bar&baz=qux"
diff --git a/ext/uri/tests/whatwg/modification/query_success_question_mark.phpt b/ext/uri/tests/whatwg/modification/query_success_question_mark.phpt
new file mode 100644
index 000000000000..18a1593a9819
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/query_success_question_mark.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - query - only a question mark character
+--EXTENSIONS--
+uri
+--FILE--
+withQuery("?");
+
+var_dump($url1->getQuery());
+var_dump($url2->getQuery());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+NULL
+NULL
+string(21) "https://example.com/?"
diff --git a/ext/uri/tests/whatwg/modification/query_success_unicode.phpt b/ext/uri/tests/whatwg/modification/query_success_unicode.phpt
new file mode 100644
index 000000000000..526138f8954a
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/query_success_unicode.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - query - unicode characters
+--EXTENSIONS--
+uri
+--FILE--
+withQuery("ő");
+
+var_dump($url1->getQuery());
+var_dump($url2->getQuery());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+NULL
+string(6) "%C5%91"
+string(27) "https://example.com/?%C5%91"
diff --git a/ext/uri/tests/whatwg/modification/query_success_unset_existing.phpt b/ext/uri/tests/whatwg/modification/query_success_unset_existing.phpt
new file mode 100644
index 000000000000..cb5a2a701e24
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/query_success_unset_existing.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - query - unsetting existing
+--EXTENSIONS--
+uri
+--FILE--
+withQuery(null);
+
+var_dump($url1->getQuery());
+var_dump($url2->getQuery());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+string(7) "foo=bar"
+NULL
+string(20) "https://example.com/"
diff --git a/ext/uri/tests/whatwg/modification/query_success_unset_non_existent.phpt b/ext/uri/tests/whatwg/modification/query_success_unset_non_existent.phpt
new file mode 100644
index 000000000000..6456dcacac7f
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/query_success_unset_non_existent.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - query - unsetting not-existent
+--EXTENSIONS--
+uri
+--FILE--
+withQuery(null);
+
+var_dump($url1->getQuery());
+var_dump($url2->getQuery());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+NULL
+NULL
+string(20) "https://example.com/"
diff --git a/ext/uri/tests/whatwg/modification/query_success_with_leading_question_mark.phpt b/ext/uri/tests/whatwg/modification/query_success_with_leading_question_mark.phpt
new file mode 100644
index 000000000000..ce67dcb6bb35
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/query_success_with_leading_question_mark.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - query - with leading question mark
+--EXTENSIONS--
+uri
+--FILE--
+withQuery("?foo=bar");
+
+var_dump($url1->getQuery());
+var_dump($url2->getQuery());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+NULL
+string(7) "foo=bar"
+string(35) "https://example.com/foo/bar?foo=bar"
diff --git a/ext/uri/tests/whatwg/modification/scheme_error_empty.phpt b/ext/uri/tests/whatwg/modification/scheme_error_empty.phpt
new file mode 100644
index 000000000000..0460fa72945f
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/scheme_error_empty.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - scheme - empty string
+--EXTENSIONS--
+uri
+--FILE--
+withScheme("");
+} catch (Uri\WhatWg\InvalidUrlException $e) {
+ echo $e->getMessage() . "\n";
+}
+
+?>
+--EXPECT--
+The specified scheme is malformed
diff --git a/ext/uri/tests/whatwg/modification/scheme_error_encoded.phpt b/ext/uri/tests/whatwg/modification/scheme_error_encoded.phpt
new file mode 100644
index 000000000000..a52dc65dadd8
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/scheme_error_encoded.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - scheme - URL encoded characters
+--EXTENSIONS--
+uri
+--FILE--
+withScheme("http%73");
+} catch (Uri\WhatWg\InvalidUrlException $e) {
+ echo $e->getMessage() . "\n";
+}
+
+?>
+--EXPECT--
+The specified scheme is malformed
diff --git a/ext/uri/tests/whatwg/modification/scheme_error_invalid.phpt b/ext/uri/tests/whatwg/modification/scheme_error_invalid.phpt
new file mode 100644
index 000000000000..21cd04346a3c
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/scheme_error_invalid.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - scheme - invalid characters
+--EXTENSIONS--
+uri
+--FILE--
+withScheme("http?");
+} catch (Uri\WhatWg\InvalidUrlException $e) {
+ echo $e->getMessage() . "\n";
+}
+
+?>
+--EXPECT--
+The specified scheme is malformed
diff --git a/ext/uri/tests/whatwg/modification/scheme_success_basic.phpt b/ext/uri/tests/whatwg/modification/scheme_success_basic.phpt
new file mode 100644
index 000000000000..6f66b30b2b7b
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/scheme_success_basic.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - scheme - basic case
+--EXTENSIONS--
+uri
+--FILE--
+withScheme("HTTP");
+
+var_dump($url1->getScheme());
+var_dump($url2->getScheme());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+string(5) "https"
+string(4) "http"
+string(19) "http://example.com/"
diff --git a/ext/uri/tests/whatwg/modification/scheme_success_colon.phpt b/ext/uri/tests/whatwg/modification/scheme_success_colon.phpt
new file mode 100644
index 000000000000..052eca6e247b
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/scheme_success_colon.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - scheme - trailing colon
+--EXTENSIONS--
+uri
+--FILE--
+withScheme("http:");
+
+var_dump($url1->getScheme());
+var_dump($url2->getScheme());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+string(5) "https"
+string(4) "http"
+string(19) "http://example.com/"
diff --git a/ext/uri/tests/whatwg/modification/scheme_success_full.phpt b/ext/uri/tests/whatwg/modification/scheme_success_full.phpt
new file mode 100644
index 000000000000..957a1fab7aff
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/scheme_success_full.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - scheme - trailing colon and double slash
+--EXTENSIONS--
+uri
+--FILE--
+withScheme("http://");
+
+var_dump($url1->getScheme());
+var_dump($url2->getScheme());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+string(5) "https"
+string(4) "http"
+string(19) "http://example.com/"
diff --git a/ext/uri/tests/whatwg/modification/username_success_auto_encoded.phpt b/ext/uri/tests/whatwg/modification/username_success_auto_encoded.phpt
new file mode 100644
index 000000000000..bc0beab49649
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/username_success_auto_encoded.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - username - characters from the percent encode set
+--EXTENSIONS--
+uri
+--FILE--
+withUsername("u:s/r");
+
+var_dump($url1->getUsername());
+var_dump($url2->getUsername());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+string(4) "user"
+string(9) "u%3As%2Fr"
+string(39) "https://u%3As%2Fr:password@example.com/"
diff --git a/ext/uri/tests/whatwg/modification/username_success_existing.phpt b/ext/uri/tests/whatwg/modification/username_success_existing.phpt
new file mode 100644
index 000000000000..2506acf85d71
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/username_success_existing.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - username - changing existing
+--EXTENSIONS--
+uri
+--FILE--
+withUsername("username");
+
+var_dump($url1->getUsername());
+var_dump($url2->getUsername());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+string(4) "user"
+string(8) "username"
+string(29) "https://username@example.com/"
diff --git a/ext/uri/tests/whatwg/modification/username_success_new.phpt b/ext/uri/tests/whatwg/modification/username_success_new.phpt
new file mode 100644
index 000000000000..56666a68ea7d
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/username_success_new.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - username - adding a new one
+--EXTENSIONS--
+uri
+--FILE--
+withUsername("username");
+
+var_dump($url1->getUsername());
+var_dump($url2->getUsername());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+NULL
+string(8) "username"
+string(29) "https://username@example.com/"
diff --git a/ext/uri/tests/whatwg/modification/username_success_unset_existing.phpt b/ext/uri/tests/whatwg/modification/username_success_unset_existing.phpt
new file mode 100644
index 000000000000..f71deff3f207
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/username_success_unset_existing.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - username - unsetting existing
+--EXTENSIONS--
+uri
+--FILE--
+withUsername(null);
+
+var_dump($url1->getUsername());
+var_dump($url2->getUsername());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+string(8) "username"
+NULL
+string(30) "https://:password@example.com/"
diff --git a/ext/uri/tests/whatwg/modification/username_success_unset_non_existent1.phpt b/ext/uri/tests/whatwg/modification/username_success_unset_non_existent1.phpt
new file mode 100644
index 000000000000..44a648610424
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/username_success_unset_non_existent1.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - username - unsetting non-existent
+--EXTENSIONS--
+uri
+--FILE--
+withUsername(null);
+
+var_dump($url1->getUsername());
+var_dump($url2->getUsername());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+NULL
+NULL
+string(20) "https://example.com/"
diff --git a/ext/uri/tests/whatwg/modification/username_success_unset_non_existent2.phpt b/ext/uri/tests/whatwg/modification/username_success_unset_non_existent2.phpt
new file mode 100644
index 000000000000..e5af4efb223d
--- /dev/null
+++ b/ext/uri/tests/whatwg/modification/username_success_unset_non_existent2.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Test Uri\WhatWg\Url component modification - username - unsetting non-existent
+--EXTENSIONS--
+uri
+--FILE--
+withUsername(null);
+
+var_dump($url1->getUsername());
+var_dump($url2->getUsername());
+var_dump($url2->toAsciiString());
+
+?>
+--EXPECT--
+NULL
+NULL
+string(30) "https://:password@example.com/"