Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/jsc/bindings/webcore/JSDOMURL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,9 @@ template<> EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSDOMURLDOMConstructor::const
EnsureStillAliveScope argument1 = callFrame->argument(1);
auto base = argument1.value().isUndefined() ? String() : convert<IDLUSVString>(*lexicalGlobalObject, argument1.value());
RETURN_IF_EXCEPTION(throwScope, {});
auto object = base.isEmpty() ? DOMURL::create(WTF::move(url)) : DOMURL::create(WTF::move(url), WTF::move(base));
// A null base means no base argument. An empty string is a real base and must be
// parsed (and rejected) like DOMURL::parse/canParse do, per the URL spec.
auto object = base.isNull() ? DOMURL::create(WTF::move(url)) : DOMURL::create(WTF::move(url), WTF::move(base));
if constexpr (IsExceptionOr<decltype(object)>)
RETURN_IF_EXCEPTION(throwScope, {});
static_assert(TypeOrExceptionOrUnderlyingType<decltype(object)>::isRef);
Expand Down
32 changes: 32 additions & 0 deletions test/js/web/url/url.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,38 @@ describe("url", () => {
);
});

// https://url.spec.whatwg.org/#url-class: a provided base is always parsed, and an
// empty string is not a valid URL, so it must be rejected even if the input is absolute.
it("rejects an empty string base", () => {
expect(() => new URL("http://example.com/", "")).toThrow(
'"http://example.com/" cannot be parsed as a URL against ""',
);
expect(() => new URL("http://example.com/", "")).toThrow(expect.objectContaining({ code: "ERR_INVALID_URL" }));
// The constructor must agree with the static validators.
expect(URL.canParse("http://example.com/", "")).toBe(false);
expect(URL.parse("http://example.com/", "")).toBeNull();
});

it("treats only an undefined base as no base", () => {
expect(new URL("http://example.com/", undefined).href).toBe("http://example.com/");
expect(new URL("http://example.com/").href).toBe("http://example.com/");
expect(URL.canParse("http://example.com/", undefined)).toBe(true);
expect(URL.parse("http://example.com/", undefined)?.href).toBe("http://example.com/");
});

// An explicit null base is coerced to the string "null" by WebIDL, which is not a
// valid URL, so it is a real (and invalid) base rather than no base.
it("treats an explicit null base as an invalid base, not as no base", () => {
// @ts-expect-error
expect(() => new URL("http://example.com/", null)).toThrow(
'"http://example.com/" cannot be parsed as a URL against "null"',
);
// @ts-expect-error
expect(URL.canParse("http://example.com/", null)).toBe(false);
// @ts-expect-error
expect(URL.parse("http://example.com/", null)).toBeNull();
});

it("should have correct origin and protocol", () => {
var url = new URL("https://example.com");
expect(url.protocol).toBe("https:");
Expand Down
Loading