diff --git a/src/bun.js/bindings/URLSearchParams.cpp b/src/bun.js/bindings/URLSearchParams.cpp index 99ac057d428fb..dd86cab765b38 100644 --- a/src/bun.js/bindings/URLSearchParams.cpp +++ b/src/bun.js/bindings/URLSearchParams.cpp @@ -86,10 +86,10 @@ String URLSearchParams::get(const String& name) const return String(); } -bool URLSearchParams::has(const String& name) const +bool URLSearchParams::has(const String& name, const String& value) const { for (const auto& pair : m_pairs) { - if (pair.key == name) + if (pair.key == name && (value.isNull() || pair.value == value)) return true; } return false; @@ -101,6 +101,7 @@ void URLSearchParams::sort() return WTF::codePointCompareLessThan(a.key, b.key); }); updateURL(); + needsSorting = false; } void URLSearchParams::set(const String& name, const String& value) @@ -147,13 +148,11 @@ Vector URLSearchParams::getAll(const String& name) const return values; } -void URLSearchParams::remove(const String& name) +void URLSearchParams::remove(const String& name, const String& value) { - if (!m_pairs.removeAllMatching([&](const auto& pair) { - return pair.key == name; - }) - && m_pairs.size() > 0) - return; + m_pairs.removeAllMatching([&](const auto& pair) { + return pair.key == name && (value.isNull() || pair.value == value); + }); updateURL(); needsSorting = true; } diff --git a/src/bun.js/bindings/URLSearchParams.h b/src/bun.js/bindings/URLSearchParams.h index ad6dc380efbf4..1443f95b6f676 100644 --- a/src/bun.js/bindings/URLSearchParams.h +++ b/src/bun.js/bindings/URLSearchParams.h @@ -44,10 +44,10 @@ class URLSearchParams : public RefCounted { } void append(const String& name, const String& value); - void remove(const String& name); + void remove(const String& name, const String& value = {}); String get(const String& name) const; Vector getAll(const String& name) const; - bool has(const String& name) const; + bool has(const String& name, const String& value = {}) const; void set(const String& name, const String& value); String toString() const; void updateFromAssociatedURL(); diff --git a/src/bun.js/bindings/webcore/JSURLSearchParams.cpp b/src/bun.js/bindings/webcore/JSURLSearchParams.cpp index ac168cd4e166d..d96185c005f94 100644 --- a/src/bun.js/bindings/webcore/JSURLSearchParams.cpp +++ b/src/bun.js/bindings/webcore/JSURLSearchParams.cpp @@ -57,6 +57,7 @@ #include #include #include "GCDefferalContext.h" +#include "wtf/StdLibExtras.h" namespace WebCore { using namespace JSC; @@ -278,7 +279,15 @@ static inline JSC::EncodedJSValue jsURLSearchParamsPrototypeFunction_deleteBody( EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); auto name = convert(*lexicalGlobalObject, argument0.value()); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); - RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.remove(WTFMove(name)); }))); + + String value; + EnsureStillAliveScope argument1 = callFrame->argument(1); + if (!argument1.value().isUndefined()) { + value = convert(*lexicalGlobalObject, argument1.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + } + + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.remove(WTFMove(name), WTFMove(value)); }))); } JSC_DEFINE_HOST_FUNCTION(jsURLSearchParamsPrototypeFunction_delete, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) @@ -338,7 +347,15 @@ static inline JSC::EncodedJSValue jsURLSearchParamsPrototypeFunction_hasBody(JSC EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); auto name = convert(*lexicalGlobalObject, argument0.value()); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); - RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS(*lexicalGlobalObject, throwScope, impl.has(WTFMove(name))))); + + String value; + EnsureStillAliveScope argument1 = callFrame->argument(1); + if (!argument1.value().isUndefined()) { + value = convert(*lexicalGlobalObject, argument1.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + } + + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS(*lexicalGlobalObject, throwScope, impl.has(WTFMove(name), WTFMove(value))))); } JSC_DEFINE_HOST_FUNCTION(jsURLSearchParamsPrototypeFunction_has, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) diff --git a/test/js/web/html/URLSearchParams.test.ts b/test/js/web/html/URLSearchParams.test.ts index 58fc6933a7a8a..35ce385dc4910 100644 --- a/test/js/web/html/URLSearchParams.test.ts +++ b/test/js/web/html/URLSearchParams.test.ts @@ -155,3 +155,19 @@ describe("URLSearchParams", () => { }); }); }); + +it(".delete second argument", () => { + const params = new URLSearchParams("a=1&a=2&b=3"); + params.delete("a", 1); + params.delete("b", undefined); + expect(params + "").toBe("a=2"); +}); + +it(".has second argument", () => { + const params = new URLSearchParams("a=1&a=2&b=3"); + expect(params.has("a", 1)).toBe(true); + expect(params.has("a", 2)).toBe(true); + expect(params.has("a", 3)).toBe(false); + expect(params.has("b", 3)).toBe(true); + expect(params.has("b", 4)).toBe(false); +});