diff options
author | 2023-02-13 00:50:15 -0800 | |
---|---|---|
committer | 2023-02-13 00:50:15 -0800 | |
commit | aa0762e4660bb17b86890b923368e5a0dc8daf7b (patch) | |
tree | a134621368f9def9a85473e90a6189afb956b457 /src/bun.js/bindings | |
parent | cdbc620104b939f7112fa613ca192e5fe6e02a7d (diff) | |
download | bun-aa0762e4660bb17b86890b923368e5a0dc8daf7b.tar.gz bun-aa0762e4660bb17b86890b923368e5a0dc8daf7b.tar.zst bun-aa0762e4660bb17b86890b923368e5a0dc8daf7b.zip |
Implement `FormData` (#2051)
* Backport std::forward change
* Implement `FormData`
* Fix io_darwin headers issue
* Implement `Blob` support in FormData
* Add test for file upload
* Fix bug with Blob not reading Content-Type
* Finish implementing FormData
* Add FormData to types
---------
Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
Diffstat (limited to 'src/bun.js/bindings')
-rw-r--r-- | src/bun.js/bindings/DOMFormData.cpp | 200 | ||||
-rw-r--r-- | src/bun.js/bindings/DOMFormData.h | 95 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGeneratedClasses.cpp | 60 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGlobalObject.cpp | 7 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGlobalObject.h | 5 | ||||
-rw-r--r-- | src/bun.js/bindings/bindings.cpp | 53 | ||||
-rw-r--r-- | src/bun.js/bindings/bindings.zig | 151 | ||||
-rw-r--r-- | src/bun.js/bindings/blob.cpp | 17 | ||||
-rw-r--r-- | src/bun.js/bindings/blob.h | 68 | ||||
-rw-r--r-- | src/bun.js/bindings/generated_classes.zig | 9 | ||||
-rw-r--r-- | src/bun.js/bindings/headers-cpp.h | 16 | ||||
-rw-r--r-- | src/bun.js/bindings/headers.h | 16 | ||||
-rw-r--r-- | src/bun.js/bindings/headers.zig | 6 | ||||
-rw-r--r-- | src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h | 4 | ||||
-rw-r--r-- | src/bun.js/bindings/webcore/DOMIsoSubspaces.h | 4 | ||||
-rw-r--r-- | src/bun.js/bindings/webcore/JSDOMFormData.cpp | 654 | ||||
-rw-r--r-- | src/bun.js/bindings/webcore/JSDOMFormData.dep | 1 | ||||
-rw-r--r-- | src/bun.js/bindings/webcore/JSDOMFormData.h | 93 |
18 files changed, 1447 insertions, 12 deletions
diff --git a/src/bun.js/bindings/DOMFormData.cpp b/src/bun.js/bindings/DOMFormData.cpp new file mode 100644 index 000000000..6c204c5f4 --- /dev/null +++ b/src/bun.js/bindings/DOMFormData.cpp @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "DOMFormData.h" +#include "wtf/URLParser.h" + +namespace WebCore { + +DOMFormData::DOMFormData(ScriptExecutionContext* context) + : ContextDestructionObserver(context) +{ +} + +Ref<DOMFormData> DOMFormData::create(ScriptExecutionContext* context) +{ + return adoptRef(*new DOMFormData(context)); +} + +Ref<DOMFormData> DOMFormData::create(ScriptExecutionContext* context, StringView urlEncodedString) +{ + auto newFormData = adoptRef(*new DOMFormData(context)); + for (auto& entry : WTF::URLParser::parseURLEncodedForm(urlEncodedString)) { + newFormData->append(entry.key, entry.value); + } + + return newFormData; +} + +String DOMFormData::toURLEncodedString() +{ + WTF::URLParser::URLEncodedForm form; + form.reserveInitialCapacity(m_items.size()); + for (auto& item : m_items) { + if (auto value = std::get_if<String>(&item.data)) + form.append({ item.name, *value }); + } + + return WTF::URLParser::serialize(form); +} + +extern "C" void DOMFormData__forEach(DOMFormData* form, void* context, void (*callback)(void* context, ZigString*, void*, ZigString*, uint8_t)) +{ + for (auto& item : form->items()) { + auto name = toZigString(item.name); + if (auto value = std::get_if<String>(&item.data)) { + auto value_ = toZigString(*value); + callback(context, &name, &value_, nullptr, 0); + } else if (auto value = std::get_if<RefPtr<Blob>>(&item.data)) { + auto filename = toZigString(value->get()->fileName()); + callback(context, &name, value->get()->impl(), &filename, 1); + } + } +} + +Ref<DOMFormData> DOMFormData::clone() const +{ + auto newFormData = adoptRef(*new DOMFormData(scriptExecutionContext())); + newFormData->m_items = m_items; + + return newFormData; +} + +// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#create-an-entry +static auto createStringEntry(const String& name, const String& value) -> DOMFormData::Item +{ + return { + replaceUnpairedSurrogatesWithReplacementCharacter(String(name)), + replaceUnpairedSurrogatesWithReplacementCharacter(String(value)), + }; +} + +void DOMFormData::append(const String& name, const String& value) +{ + m_items.append(createStringEntry(name, value)); +} + +void DOMFormData::append(const String& name, RefPtr<Blob> blob, const String& filename) +{ + blob->setFileName(replaceUnpairedSurrogatesWithReplacementCharacter(String(filename))); + m_items.append({ replaceUnpairedSurrogatesWithReplacementCharacter(String(name)), blob }); +} +void DOMFormData::remove(const String& name) +{ + m_items.removeAllMatching([&name](const auto& item) { + return item.name == name; + }); +} + +auto DOMFormData::get(const String& name) -> std::optional<FormDataEntryValue> +{ + for (auto& item : m_items) { + if (item.name == name) + return item.data; + } + + return std::nullopt; +} + +auto DOMFormData::getAll(const String& name) -> Vector<FormDataEntryValue> +{ + Vector<FormDataEntryValue> result; + + for (auto& item : m_items) { + if (item.name == name) + result.append(item.data); + } + + return result; +} + +bool DOMFormData::has(const String& name) +{ + for (auto& item : m_items) { + if (item.name == name) + return true; + } + + return false; +} + +void DOMFormData::set(const String& name, const String& value) +{ + set(name, { name, value }); +} + +void DOMFormData::set(const String& name, RefPtr<Blob> blob, const String& filename) +{ + blob->setFileName(filename); + set(name, { name, blob }); +} + +void DOMFormData::set(const String& name, Item&& item) +{ + std::optional<size_t> initialMatchLocation; + + // Find location of the first item with a matching name. + for (size_t i = 0; i < m_items.size(); ++i) { + if (name == m_items[i].name) { + initialMatchLocation = i; + break; + } + } + + if (initialMatchLocation) { + m_items[*initialMatchLocation] = WTFMove(item); + + m_items.removeAllMatching([&name](const auto& item) { + return item.name == name; + }, + *initialMatchLocation + 1); + return; + } + + m_items.append(WTFMove(item)); +} + +DOMFormData::Iterator::Iterator(DOMFormData& target) + : m_target(target) +{ +} + +std::optional<KeyValuePair<String, DOMFormData::FormDataEntryValue>> DOMFormData::Iterator::next() +{ + auto& items = m_target->items(); + if (m_index >= items.size()) + return std::nullopt; + + auto& item = items[m_index++]; + return makeKeyValuePair(item.name, item.data); +} + +} // namespace WebCore diff --git a/src/bun.js/bindings/DOMFormData.h b/src/bun.js/bindings/DOMFormData.h new file mode 100644 index 000000000..0970d9064 --- /dev/null +++ b/src/bun.js/bindings/DOMFormData.h @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "ContextDestructionObserver.h" +#include <variant> +#include <wtf/RefCounted.h> +#include <wtf/text/WTFString.h> +#include "blob.h" +namespace WebCore { + +template<typename> class ExceptionOr; +class HTMLElement; +class HTMLFormElement; + +class DOMFormData : public RefCounted<DOMFormData>, public ContextDestructionObserver { +public: + using FormDataEntryValue = std::variant<String, RefPtr<Blob>>; + + struct Item { + String name; + FormDataEntryValue data; + }; + + // static Ref<DOMFormData> create(ScriptExecutionContext*, const PAL::TextEncoding&); + static Ref<DOMFormData> create(ScriptExecutionContext*); + static Ref<DOMFormData> create(ScriptExecutionContext*, StringView urlEncodedString); + + const Vector<Item>& items() const { return m_items; } + // const PAL::TextEncoding& encoding() const { return m_encoding; } + + void append(const String& name, const String& value); + void append(const String& name, RefPtr<Blob>, const String& filename = {}); + void remove(const String& name); + std::optional<FormDataEntryValue> get(const String& name); + Vector<FormDataEntryValue> getAll(const String& name); + bool has(const String& name); + void set(const String& name, const String& value); + void set(const String& name, RefPtr<Blob>, const String& filename = {}); + Ref<DOMFormData> clone() const; + + size_t count() const { return m_items.size(); } + + String toURLEncodedString(); + + class Iterator { + public: + explicit Iterator(DOMFormData&); + std::optional<KeyValuePair<String, FormDataEntryValue>> next(); + + private: + Ref<DOMFormData> m_target; + size_t m_index { 0 }; + }; + Iterator createIterator() { return Iterator { *this }; } + +private: + // explicit DOMFormData(ScriptExecutionContext*, const PAL::TextEncoding& = PAL::UTF8Encoding()); + explicit DOMFormData(ScriptExecutionContext*); + + void set(const String& name, Item&&); + + // PAL::TextEncoding m_encoding; + Vector<Item> m_items; +}; + +} // namespace WebCore diff --git a/src/bun.js/bindings/ZigGeneratedClasses.cpp b/src/bun.js/bindings/ZigGeneratedClasses.cpp index ac321a520..c1e7f674f 100644 --- a/src/bun.js/bindings/ZigGeneratedClasses.cpp +++ b/src/bun.js/bindings/ZigGeneratedClasses.cpp @@ -103,6 +103,9 @@ extern "C" void BlobClass__finalize(void*); extern "C" EncodedJSValue BlobPrototype__getArrayBuffer(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); JSC_DECLARE_HOST_FUNCTION(BlobPrototype__arrayBufferCallback); +extern "C" EncodedJSValue BlobPrototype__getFormData(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); +JSC_DECLARE_HOST_FUNCTION(BlobPrototype__formDataCallback); + extern "C" EncodedJSValue BlobPrototype__getJSON(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); JSC_DECLARE_HOST_FUNCTION(BlobPrototype__jsonCallback); @@ -131,6 +134,7 @@ STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSBlobPrototype, JSBlobPrototype::Base); static const HashTableValue JSBlobPrototypeTableValues[] = { { "arrayBuffer"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, BlobPrototype__arrayBufferCallback, 0 } }, + { "formData"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, BlobPrototype__formDataCallback, 0 } }, { "json"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, BlobPrototype__jsonCallback, 0 } }, { "size"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, BlobPrototype__sizeGetterWrap, 0 } }, { "slice"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, BlobPrototype__sliceCallback, 2 } }, @@ -170,6 +174,22 @@ JSC_DEFINE_HOST_FUNCTION(BlobPrototype__arrayBufferCallback, (JSGlobalObject * l return BlobPrototype__getArrayBuffer(thisObject->wrapped(), lexicalGlobalObject, callFrame); } +JSC_DEFINE_HOST_FUNCTION(BlobPrototype__formDataCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + auto& vm = lexicalGlobalObject->vm(); + + JSBlob* thisObject = jsDynamicCast<JSBlob*>(callFrame->thisValue()); + + if (UNLIKELY(!thisObject)) { + auto throwScope = DECLARE_THROW_SCOPE(vm); + return throwVMTypeError(lexicalGlobalObject, throwScope); + } + + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + + return BlobPrototype__getFormData(thisObject->wrapped(), lexicalGlobalObject, callFrame); +} + JSC_DEFINE_HOST_FUNCTION(BlobPrototype__jsonCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) { auto& vm = lexicalGlobalObject->vm(); @@ -6154,6 +6174,9 @@ JSC_DECLARE_CUSTOM_GETTER(RequestPrototype__credentialsGetterWrap); extern "C" JSC::EncodedJSValue RequestPrototype__getDestination(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject); JSC_DECLARE_CUSTOM_GETTER(RequestPrototype__destinationGetterWrap); +extern "C" EncodedJSValue RequestPrototype__getFormData(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); +JSC_DECLARE_HOST_FUNCTION(RequestPrototype__formDataCallback); + extern "C" JSC::EncodedJSValue RequestPrototype__getHeaders(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject); JSC_DECLARE_CUSTOM_GETTER(RequestPrototype__headersGetterWrap); @@ -6195,6 +6218,7 @@ static const HashTableValue JSRequestPrototypeTableValues[] = { { "clone"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, RequestPrototype__cloneCallback, 1 } }, { "credentials"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, RequestPrototype__credentialsGetterWrap, 0 } }, { "destination"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, RequestPrototype__destinationGetterWrap, 0 } }, + { "formData"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, RequestPrototype__formDataCallback, 0 } }, { "headers"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, RequestPrototype__headersGetterWrap, 0 } }, { "integrity"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, RequestPrototype__integrityGetterWrap, 0 } }, { "json"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, RequestPrototype__jsonCallback, 0 } }, @@ -6348,6 +6372,22 @@ JSC_DEFINE_CUSTOM_GETTER(RequestPrototype__destinationGetterWrap, (JSGlobalObjec RELEASE_AND_RETURN(throwScope, result); } +JSC_DEFINE_HOST_FUNCTION(RequestPrototype__formDataCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + auto& vm = lexicalGlobalObject->vm(); + + JSRequest* thisObject = jsDynamicCast<JSRequest*>(callFrame->thisValue()); + + if (UNLIKELY(!thisObject)) { + auto throwScope = DECLARE_THROW_SCOPE(vm); + return throwVMTypeError(lexicalGlobalObject, throwScope); + } + + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + + return RequestPrototype__getFormData(thisObject->wrapped(), lexicalGlobalObject, callFrame); +} + JSC_DEFINE_CUSTOM_GETTER(RequestPrototype__headersGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) { auto& vm = lexicalGlobalObject->vm(); @@ -6795,6 +6835,9 @@ JSC_DECLARE_CUSTOM_GETTER(ResponsePrototype__bodyUsedGetterWrap); extern "C" EncodedJSValue ResponsePrototype__doClone(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); JSC_DECLARE_HOST_FUNCTION(ResponsePrototype__cloneCallback); +extern "C" EncodedJSValue ResponsePrototype__getFormData(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame); +JSC_DECLARE_HOST_FUNCTION(ResponsePrototype__formDataCallback); + extern "C" JSC::EncodedJSValue ResponsePrototype__getHeaders(void* ptr, JSC::JSGlobalObject* lexicalGlobalObject); JSC_DECLARE_CUSTOM_GETTER(ResponsePrototype__headersGetterWrap); @@ -6830,6 +6873,7 @@ static const HashTableValue JSResponsePrototypeTableValues[] = { { "body"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, ResponsePrototype__bodyGetterWrap, 0 } }, { "bodyUsed"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, ResponsePrototype__bodyUsedGetterWrap, 0 } }, { "clone"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, ResponsePrototype__cloneCallback, 1 } }, + { "formData"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, ResponsePrototype__formDataCallback, 0 } }, { "headers"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, ResponsePrototype__headersGetterWrap, 0 } }, { "json"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::NativeFunctionType, ResponsePrototype__jsonCallback, 0 } }, { "ok"_s, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::CustomAccessor | JSC::PropertyAttribute::DOMAttribute | PropertyAttribute::DontDelete), NoIntrinsic, { HashTableValue::GetterSetterType, ResponsePrototype__okGetterWrap, 0 } }, @@ -6946,6 +6990,22 @@ JSC_DEFINE_HOST_FUNCTION(ResponsePrototype__cloneCallback, (JSGlobalObject * lex return ResponsePrototype__doClone(thisObject->wrapped(), lexicalGlobalObject, callFrame); } +JSC_DEFINE_HOST_FUNCTION(ResponsePrototype__formDataCallback, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + auto& vm = lexicalGlobalObject->vm(); + + JSResponse* thisObject = jsDynamicCast<JSResponse*>(callFrame->thisValue()); + + if (UNLIKELY(!thisObject)) { + auto throwScope = DECLARE_THROW_SCOPE(vm); + return throwVMTypeError(lexicalGlobalObject, throwScope); + } + + JSC::EnsureStillAliveScope thisArg = JSC::EnsureStillAliveScope(thisObject); + + return ResponsePrototype__getFormData(thisObject->wrapped(), lexicalGlobalObject, callFrame); +} + JSC_DEFINE_CUSTOM_GETTER(ResponsePrototype__headersGetterWrap, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName)) { auto& vm = lexicalGlobalObject->vm(); diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index ce29e43a6..bcb462d42 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -167,6 +167,8 @@ namespace JSCastingHelpers = JSC::JSCastingHelpers; #include "webcrypto/JSCryptoKey.h" #include "webcrypto/JSSubtleCrypto.h" +#include "JSDOMFormData.h" + constexpr size_t DEFAULT_ERROR_STACK_TRACE_LIMIT = 10; #ifdef __APPLE__ @@ -614,6 +616,9 @@ WEBCORE_GENERATED_CONSTRUCTOR_SETTER(JSTextEncoder); WEBCORE_GENERATED_CONSTRUCTOR_GETTER(JSURLSearchParams); WEBCORE_GENERATED_CONSTRUCTOR_SETTER(JSURLSearchParams); +WEBCORE_GENERATED_CONSTRUCTOR_GETTER(JSDOMFormData); +WEBCORE_GENERATED_CONSTRUCTOR_SETTER(JSDOMFormData); + JSC_DECLARE_CUSTOM_GETTER(JSEvent_getter); JSC_DEFINE_CUSTOM_GETTER(JSEvent_getter, @@ -3234,6 +3239,7 @@ void GlobalObject::addBuiltinGlobals(JSC::VM& vm) JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::ReadOnly); PUT_WEBCORE_GENERATED_CONSTRUCTOR("TextEncoder"_s, JSTextEncoder); + PUT_WEBCORE_GENERATED_CONSTRUCTOR("FormData"_s, JSDOMFormData); PUT_WEBCORE_GENERATED_CONSTRUCTOR("MessageEvent"_s, JSMessageEvent); PUT_WEBCORE_GENERATED_CONSTRUCTOR("WebSocket"_s, JSWebSocket); PUT_WEBCORE_GENERATED_CONSTRUCTOR("Headers"_s, JSFetchHeaders); @@ -3552,6 +3558,7 @@ void GlobalObject::visitChildrenImpl(JSCell* cell, Visitor& visitor) visitor.append(thisObject->m_JSFetchHeadersSetterValue); visitor.append(thisObject->m_JSTextEncoderSetterValue); visitor.append(thisObject->m_JSURLSearchParamsSetterValue); + visitor.append(thisObject->m_JSDOMFormDataSetterValue); thisObject->m_JSArrayBufferSinkClassStructure.visit(visitor); thisObject->m_JSBufferListClassStructure.visit(visitor); diff --git a/src/bun.js/bindings/ZigGlobalObject.h b/src/bun.js/bindings/ZigGlobalObject.h index 2b688f09d..cad68f79a 100644 --- a/src/bun.js/bindings/ZigGlobalObject.h +++ b/src/bun.js/bindings/ZigGlobalObject.h @@ -89,9 +89,9 @@ public: return WebCore::subspaceForImpl<GlobalObject, WebCore::UseCustomHeapCellType::Yes>( vm, [](auto& spaces) { return spaces.m_clientSubspaceForWorkerGlobalScope.get(); }, - [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForWorkerGlobalScope = WTFMove(space); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForWorkerGlobalScope = std::forward<decltype(space)>(space); }, [](auto& spaces) { return spaces.m_subspaceForWorkerGlobalScope.get(); }, - [](auto& spaces, auto&& space) { spaces.m_subspaceForWorkerGlobalScope = WTFMove(space); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForWorkerGlobalScope = std::forward<decltype(space)>(space); }, [](auto& server) -> JSC::HeapCellType& { return server.m_heapCellTypeForJSWorkerGlobalScope; }); } @@ -344,6 +344,7 @@ public: mutable WriteBarrier<Unknown> m_JSTextEncoderSetterValue; mutable WriteBarrier<Unknown> m_JSURLSearchParamsSetterValue; mutable WriteBarrier<Unknown> m_JSWebSocketSetterValue; + mutable WriteBarrier<Unknown> m_JSDOMFormDataSetterValue; mutable WriteBarrier<JSFunction> m_thenables[promiseFunctionsSize + 1]; diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index 02a79c1b0..aa8a28601 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -85,6 +85,10 @@ #include "JavaScriptCore/HashMapImpl.h" #include "JavaScriptCore/HashMapImplInlines.h" +#include "DOMFormData.h" +#include "JSDOMFormData.h" +#include "ZigGeneratedClasses.h" + template<typename UWSResponse> static void copyToUWS(WebCore::FetchHeaders* headers, UWSResponse* res) { @@ -3726,4 +3730,53 @@ extern "C" void JSC__JSGlobalObject__queueMicrotaskJob(JSC__JSGlobalObject* arg0 JSC::JSValue::decode(JSValue2), JSC::JSValue::decode(JSValue3), JSC::JSValue::decode(JSValue4)); +} + +#pragma mark - WebCore::DOMFormData + +CPP_DECL void WebCore__DOMFormData__append(WebCore__DOMFormData* arg0, ZigString* arg1, ZigString* arg2) +{ + arg0->append(toStringCopy(*arg1), toStringCopy(*arg2)); +} + +CPP_DECL void WebCore__DOMFormData__appendBlob(WebCore__DOMFormData* arg0, JSC__JSGlobalObject* arg1, ZigString* arg2, void* blobValueInner, ZigString* fileName) +{ + RefPtr<Blob> blob = WebCore::Blob::create(blobValueInner); + arg0->append(toStringCopy(*arg2), blob, toStringCopy(*fileName)); +} +CPP_DECL size_t WebCore__DOMFormData__count(WebCore__DOMFormData* arg0) +{ + return arg0->count(); +} + +extern "C" void DOMFormData__toQueryString( + DOMFormData* formData, + void* ctx, + void (*callback)(void* ctx, ZigString* encoded)) +{ + auto str = formData->toURLEncodedString(); + ZigString encoded = toZigString(str); + callback(ctx, &encoded); +} + +CPP_DECL JSC__JSValue WebCore__DOMFormData__createFromURLQuery(JSC__JSGlobalObject* arg0, ZigString* arg1) +{ + JSC::VM& vm = arg0->vm(); + Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(arg0); + // don't need to copy the string because it internally does. + auto formData = DOMFormData::create(globalObject->scriptExecutionContext(), toString(*arg1)); + return JSValue::encode(toJSNewlyCreated(arg0, globalObject, WTFMove(formData))); +} + +CPP_DECL JSC__JSValue WebCore__DOMFormData__create(JSC__JSGlobalObject* arg0) +{ + JSC::VM& vm = arg0->vm(); + Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(arg0); + auto formData = DOMFormData::create(globalObject->scriptExecutionContext()); + return JSValue::encode(toJSNewlyCreated(arg0, globalObject, WTFMove(formData))); +} + +CPP_DECL WebCore__DOMFormData* WebCore__DOMFormData__fromJS(JSC__JSValue JSValue1) +{ + return WebCoreCast<WebCore::JSDOMFormData, WebCore__DOMFormData>(JSValue1); }
\ No newline at end of file diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig index 447c6c043..d0ccacd06 100644 --- a/src/bun.js/bindings/bindings.zig +++ b/src/bun.js/bindings/bindings.zig @@ -794,6 +794,157 @@ pub const DOMURL = opaque { const Api = @import("../../api/schema.zig").Api; +pub const DOMFormData = opaque { + pub const shim = Shimmer("WebCore", "DOMFormData", @This()); + + pub const name = "WebCore::DOMFormData"; + pub const include = "DOMFormData.h"; + pub const namespace = "WebCore"; + + const cppFn = shim.cppFn; + + pub fn create( + global: *JSGlobalObject, + ) JSValue { + return shim.cppFn("create", .{ + global, + }); + } + + pub fn createFromURLQuery( + global: *JSGlobalObject, + query: *ZigString, + ) JSValue { + return shim.cppFn("createFromURLQuery", .{ + global, + query, + }); + } + + extern fn DOMFormData__toQueryString( + *DOMFormData, + ctx: *anyopaque, + callback: *const fn (ctx: *anyopaque, *ZigString) callconv(.C) void, + ) void; + + pub fn toQueryString( + this: *DOMFormData, + comptime Ctx: type, + ctx: Ctx, + comptime callback: fn (ctx: Ctx, ZigString) callconv(.C) void, + ) void { + const Wrapper = struct { + const cb = callback; + pub fn run(c: *anyopaque, str: *ZigString) callconv(.C) void { + cb(@ptrCast(Ctx, c), str.*); + } + }; + + DOMFormData__toQueryString(this, ctx, &Wrapper.run); + } + + pub fn fromJS( + value: JSValue, + ) ?*DOMFormData { + return shim.cppFn("fromJS", .{ + value, + }); + } + + pub fn append( + this: *DOMFormData, + name_: *ZigString, + value_: *ZigString, + ) void { + return shim.cppFn("append", .{ + this, + name_, + value_, + }); + } + + pub fn appendBlob( + this: *DOMFormData, + global: *JSC.JSGlobalObject, + name_: *ZigString, + blob: *anyopaque, + filename_: *ZigString, + ) void { + return shim.cppFn("appendBlob", .{ + this, + global, + name_, + blob, + filename_, + }); + } + + pub fn count( + this: *DOMFormData, + ) usize { + return shim.cppFn("count", .{ + this, + }); + } + + const ForEachFunction = *const fn ( + ctx_ptr: ?*anyopaque, + name: *ZigString, + value_ptr: *anyopaque, + filename: ?*ZigString, + is_blob: u8, + ) callconv(.C) void; + + extern fn DOMFormData__forEach(*DOMFormData, ?*anyopaque, ForEachFunction) void; + pub const FormDataEntry = union(enum) { + string: ZigString, + file: struct { + blob: *JSC.WebCore.Blob, + filename: ZigString, + }, + }; + pub fn forEach( + this: *DOMFormData, + comptime Context: type, + ctx: *Context, + comptime callback_wrapper: *const fn (ctx: *Context, name: ZigString, value: FormDataEntry) void, + ) void { + const Wrap = struct { + const wrapper = callback_wrapper; + pub fn forEachWrapper( + ctx_ptr: ?*anyopaque, + name_: *ZigString, + value_ptr: *anyopaque, + filename: ?*ZigString, + is_blob: u8, + ) callconv(.C) void { + var ctx_ = bun.cast(*Context, ctx_ptr.?); + const value = if (is_blob == 0) + FormDataEntry{ .string = bun.cast(*ZigString, value_ptr).* } + else + FormDataEntry{ + .file = .{ + .blob = bun.cast(*JSC.WebCore.Blob, value_ptr), + .filename = (filename orelse &ZigString.Empty).*, + }, + }; + + wrapper(ctx_, name_.*, value); + } + }; + JSC.markBinding(@src()); + DOMFormData__forEach(this, ctx, Wrap.forEachWrapper); + } + + pub const Extern = [_][]const u8{ + "create", + "fromJS", + "append", + "appendBlob", + "count", + "createFromURLQuery", + }; +}; pub const FetchHeaders = opaque { pub const shim = Shimmer("WebCore", "FetchHeaders", @This()); diff --git a/src/bun.js/bindings/blob.cpp b/src/bun.js/bindings/blob.cpp new file mode 100644 index 000000000..257f230e1 --- /dev/null +++ b/src/bun.js/bindings/blob.cpp @@ -0,0 +1,17 @@ +#include "blob.h" + +extern "C" JSC::EncodedJSValue Blob__create(JSC::JSGlobalObject* globalObject, void* impl); + +namespace WebCore { + +JSC::JSValue toJS(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, WebCore::Blob& impl) +{ + return JSC::JSValue::decode(Blob__create(lexicalGlobalObject, Blob__dupe(impl.impl()))); +} + +JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, Ref<WebCore::Blob>&& impl) +{ + return JSC::JSValue::decode(Blob__create(lexicalGlobalObject, impl->impl())); +} + +}
\ No newline at end of file diff --git a/src/bun.js/bindings/blob.h b/src/bun.js/bindings/blob.h new file mode 100644 index 000000000..83d6ff3af --- /dev/null +++ b/src/bun.js/bindings/blob.h @@ -0,0 +1,68 @@ +#pragma once + +#include "root.h" +#include "JSDOMGlobalObject.h" + +namespace WebCore { + +extern "C" void* Blob__dupeFromJS(JSC::EncodedJSValue impl); +extern "C" void* Blob__dupe(void* impl); +extern "C" void Blob__destroy(void* impl); + +class Blob : public RefCounted<Blob> { +public: + void* impl() + { + return m_impl; + } + + static RefPtr<Blob> create(JSC::JSValue impl) + { + void* implPtr = Blob__dupeFromJS(JSValue::encode(impl)); + if (!implPtr) + return nullptr; + + return adoptRef(*new Blob(implPtr)); + } + + static RefPtr<Blob> create(void* ptr) + { + void* implPtr = Blob__dupe(ptr); + if (!implPtr) + return nullptr; + + return adoptRef(*new Blob(implPtr)); + } + + ~Blob() + { + Blob__destroy(m_impl); + } + + String fileName() + { + return m_fileName; + } + + void setFileName(String fileName) + { + m_fileName = fileName; + } + +private: + Blob(void* impl, String fileName = String()) + { + m_impl = impl; + m_fileName = fileName; + } + + void* m_impl; + String m_fileName; +}; + +JSC::JSValue toJS(JSC::JSGlobalObject*, JSDOMGlobalObject*, Blob&); +inline JSC::JSValue toJS(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, Blob* impl) { return impl ? toJS(lexicalGlobalObject, globalObject, *impl) : JSC::jsNull(); } +JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject*, Ref<Blob>&&); +inline JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, RefPtr<Blob>&& impl) { return impl ? toJSNewlyCreated(lexicalGlobalObject, globalObject, impl.releaseNonNull()) : JSC::jsNull(); } + +} diff --git a/src/bun.js/bindings/generated_classes.zig b/src/bun.js/bindings/generated_classes.zig index 2f4e7b0b6..599d05d7e 100644 --- a/src/bun.js/bindings/generated_classes.zig +++ b/src/bun.js/bindings/generated_classes.zig @@ -86,6 +86,8 @@ pub const JSBlob = struct { if (@TypeOf(Blob.getArrayBuffer) != CallbackType) @compileLog("Expected Blob.getArrayBuffer to be a callback but received " ++ @typeName(@TypeOf(Blob.getArrayBuffer))); + if (@TypeOf(Blob.getFormData) != CallbackType) + @compileLog("Expected Blob.getFormData to be a callback but received " ++ @typeName(@TypeOf(Blob.getFormData))); if (@TypeOf(Blob.getJSON) != CallbackType) @compileLog("Expected Blob.getJSON to be a callback but received " ++ @typeName(@TypeOf(Blob.getJSON))); if (@TypeOf(Blob.getSize) != GetterType) @@ -108,6 +110,7 @@ pub const JSBlob = struct { @export(Blob.constructor, .{ .name = "BlobClass__construct" }); @export(Blob.finalize, .{ .name = "BlobClass__finalize" }); @export(Blob.getArrayBuffer, .{ .name = "BlobPrototype__getArrayBuffer" }); + @export(Blob.getFormData, .{ .name = "BlobPrototype__getFormData" }); @export(Blob.getJSON, .{ .name = "BlobPrototype__getJSON" }); @export(Blob.getSize, .{ .name = "BlobPrototype__getSize" }); @export(Blob.getSlice, .{ .name = "BlobPrototype__getSlice" }); @@ -1771,6 +1774,8 @@ pub const JSRequest = struct { if (@TypeOf(Request.getDestination) != GetterType) @compileLog("Expected Request.getDestination to be a getter"); + if (@TypeOf(Request.getFormData) != CallbackType) + @compileLog("Expected Request.getFormData to be a callback but received " ++ @typeName(@TypeOf(Request.getFormData))); if (@TypeOf(Request.getHeaders) != GetterType) @compileLog("Expected Request.getHeaders to be a getter"); @@ -1811,6 +1816,7 @@ pub const JSRequest = struct { @export(Request.getCache, .{ .name = "RequestPrototype__getCache" }); @export(Request.getCredentials, .{ .name = "RequestPrototype__getCredentials" }); @export(Request.getDestination, .{ .name = "RequestPrototype__getDestination" }); + @export(Request.getFormData, .{ .name = "RequestPrototype__getFormData" }); @export(Request.getHeaders, .{ .name = "RequestPrototype__getHeaders" }); @export(Request.getIntegrity, .{ .name = "RequestPrototype__getIntegrity" }); @export(Request.getJSON, .{ .name = "RequestPrototype__getJSON" }); @@ -1990,6 +1996,8 @@ pub const JSResponse = struct { if (@TypeOf(Response.doClone) != CallbackType) @compileLog("Expected Response.doClone to be a callback but received " ++ @typeName(@TypeOf(Response.doClone))); + if (@TypeOf(Response.getFormData) != CallbackType) + @compileLog("Expected Response.getFormData to be a callback but received " ++ @typeName(@TypeOf(Response.getFormData))); if (@TypeOf(Response.getHeaders) != GetterType) @compileLog("Expected Response.getHeaders to be a getter"); @@ -2033,6 +2041,7 @@ pub const JSResponse = struct { @export(Response.getBlob, .{ .name = "ResponsePrototype__getBlob" }); @export(Response.getBody, .{ .name = "ResponsePrototype__getBody" }); @export(Response.getBodyUsed, .{ .name = "ResponsePrototype__getBodyUsed" }); + @export(Response.getFormData, .{ .name = "ResponsePrototype__getFormData" }); @export(Response.getHeaders, .{ .name = "ResponsePrototype__getHeaders" }); @export(Response.getJSON, .{ .name = "ResponsePrototype__getJSON" }); @export(Response.getOK, .{ .name = "ResponsePrototype__getOK" }); diff --git a/src/bun.js/bindings/headers-cpp.h b/src/bun.js/bindings/headers-cpp.h index f1e7de1dd..4dc7a2143 100644 --- a/src/bun.js/bindings/headers-cpp.h +++ b/src/bun.js/bindings/headers-cpp.h @@ -1,4 +1,4 @@ -//-- AUTOGENERATED FILE -- 1674546420 +//-- AUTOGENERATED FILE -- 1676266700 // clang-format off #pragma once @@ -16,6 +16,14 @@ extern "C" const size_t JSC__JSObject_object_size_ = sizeof(JSC::JSObject); extern "C" const size_t JSC__JSObject_object_align_ = alignof(JSC::JSObject); +#ifndef INCLUDED_DOMFormData_h +#define INCLUDED_DOMFormData_h +#include "DOMFormData.h" +#endif + +extern "C" const size_t WebCore__DOMFormData_object_size_ = sizeof(WebCore::DOMFormData); +extern "C" const size_t WebCore__DOMFormData_object_align_ = alignof(WebCore::DOMFormData); + #ifndef INCLUDED_FetchHeaders_h #define INCLUDED_FetchHeaders_h #include "FetchHeaders.h" @@ -152,8 +160,8 @@ extern "C" const size_t Zig__ConsoleClient_object_align_ = alignof(Zig::ConsoleC extern "C" const size_t Bun__Timer_object_size_ = sizeof(Bun__Timer); extern "C" const size_t Bun__Timer_object_align_ = alignof(Bun__Timer); -const size_t sizes[38] = {sizeof(JSC::JSObject), sizeof(WebCore::DOMURL), sizeof(WebCore::FetchHeaders), sizeof(SystemError), sizeof(JSC::JSCell), sizeof(JSC::JSString), sizeof(JSC::JSModuleLoader), sizeof(JSC::JSPromise), sizeof(JSC::JSInternalPromise), sizeof(JSC::JSFunction), sizeof(JSC::JSGlobalObject), sizeof(JSC::JSValue), sizeof(JSC::Exception), sizeof(JSC::VM), sizeof(JSC::ThrowScope), sizeof(JSC::CatchScope), sizeof(FFI__ptr), sizeof(Reader__u8), sizeof(Reader__u16), sizeof(Reader__u32), sizeof(Reader__ptr), sizeof(Reader__i8), sizeof(Reader__i16), sizeof(Reader__i32), sizeof(Reader__f32), sizeof(Reader__f64), sizeof(Reader__i64), sizeof(Reader__u64), sizeof(Reader__intptr), sizeof(Crypto__getRandomValues), sizeof(Crypto__randomUUID), sizeof(Crypto__timingSafeEqual), sizeof(Zig::GlobalObject), sizeof(Bun__Path), sizeof(ArrayBufferSink), sizeof(HTTPSResponseSink), sizeof(HTTPResponseSink), sizeof(FileSink)}; +const size_t sizes[39] = {sizeof(JSC::JSObject), sizeof(WebCore::DOMURL), sizeof(WebCore::DOMFormData), sizeof(WebCore::FetchHeaders), sizeof(SystemError), sizeof(JSC::JSCell), sizeof(JSC::JSString), sizeof(JSC::JSModuleLoader), sizeof(JSC::JSPromise), sizeof(JSC::JSInternalPromise), sizeof(JSC::JSFunction), sizeof(JSC::JSGlobalObject), sizeof(JSC::JSValue), sizeof(JSC::Exception), sizeof(JSC::VM), sizeof(JSC::ThrowScope), sizeof(JSC::CatchScope), sizeof(FFI__ptr), sizeof(Reader__u8), sizeof(Reader__u16), sizeof(Reader__u32), sizeof(Reader__ptr), sizeof(Reader__i8), sizeof(Reader__i16), sizeof(Reader__i32), sizeof(Reader__f32), sizeof(Reader__f64), sizeof(Reader__i64), sizeof(Reader__u64), sizeof(Reader__intptr), sizeof(Crypto__getRandomValues), sizeof(Crypto__randomUUID), sizeof(Crypto__timingSafeEqual), sizeof(Zig::GlobalObject), sizeof(Bun__Path), sizeof(ArrayBufferSink), sizeof(HTTPSResponseSink), sizeof(HTTPResponseSink), sizeof(FileSink)}; -const char* names[38] = {"JSC__JSObject", "WebCore__DOMURL", "WebCore__FetchHeaders", "SystemError", "JSC__JSCell", "JSC__JSString", "JSC__JSModuleLoader", "JSC__JSPromise", "JSC__JSInternalPromise", "JSC__JSFunction", "JSC__JSGlobalObject", "JSC__JSValue", "JSC__Exception", "JSC__VM", "JSC__ThrowScope", "JSC__CatchScope", "FFI__ptr", "Reader__u8", "Reader__u16", "Reader__u32", "Reader__ptr", "Reader__i8", "Reader__i16", "Reader__i32", "Reader__f32", "Reader__f64", "Reader__i64", "Reader__u64", "Reader__intptr", "Crypto__getRandomValues", "Crypto__randomUUID", "Crypto__timingSafeEqual", "Zig__GlobalObject", "Bun__Path", "ArrayBufferSink", "HTTPSResponseSink", "HTTPResponseSink", "FileSink"}; +const char* names[39] = {"JSC__JSObject", "WebCore__DOMURL", "WebCore__DOMFormData", "WebCore__FetchHeaders", "SystemError", "JSC__JSCell", "JSC__JSString", "JSC__JSModuleLoader", "JSC__JSPromise", "JSC__JSInternalPromise", "JSC__JSFunction", "JSC__JSGlobalObject", "JSC__JSValue", "JSC__Exception", "JSC__VM", "JSC__ThrowScope", "JSC__CatchScope", "FFI__ptr", "Reader__u8", "Reader__u16", "Reader__u32", "Reader__ptr", "Reader__i8", "Reader__i16", "Reader__i32", "Reader__f32", "Reader__f64", "Reader__i64", "Reader__u64", "Reader__intptr", "Crypto__getRandomValues", "Crypto__randomUUID", "Crypto__timingSafeEqual", "Zig__GlobalObject", "Bun__Path", "ArrayBufferSink", "HTTPSResponseSink", "HTTPResponseSink", "FileSink"}; -const size_t aligns[38] = {alignof(JSC::JSObject), alignof(WebCore::DOMURL), alignof(WebCore::FetchHeaders), alignof(SystemError), alignof(JSC::JSCell), alignof(JSC::JSString), alignof(JSC::JSModuleLoader), alignof(JSC::JSPromise), alignof(JSC::JSInternalPromise), alignof(JSC::JSFunction), alignof(JSC::JSGlobalObject), alignof(JSC::JSValue), alignof(JSC::Exception), alignof(JSC::VM), alignof(JSC::ThrowScope), alignof(JSC::CatchScope), alignof(FFI__ptr), alignof(Reader__u8), alignof(Reader__u16), alignof(Reader__u32), alignof(Reader__ptr), alignof(Reader__i8), alignof(Reader__i16), alignof(Reader__i32), alignof(Reader__f32), alignof(Reader__f64), alignof(Reader__i64), alignof(Reader__u64), alignof(Reader__intptr), alignof(Crypto__getRandomValues), alignof(Crypto__randomUUID), alignof(Crypto__timingSafeEqual), alignof(Zig::GlobalObject), alignof(Bun__Path), alignof(ArrayBufferSink), alignof(HTTPSResponseSink), alignof(HTTPResponseSink), alignof(FileSink)}; +const size_t aligns[39] = {alignof(JSC::JSObject), alignof(WebCore::DOMURL), alignof(WebCore::DOMFormData), alignof(WebCore::FetchHeaders), alignof(SystemError), alignof(JSC::JSCell), alignof(JSC::JSString), alignof(JSC::JSModuleLoader), alignof(JSC::JSPromise), alignof(JSC::JSInternalPromise), alignof(JSC::JSFunction), alignof(JSC::JSGlobalObject), alignof(JSC::JSValue), alignof(JSC::Exception), alignof(JSC::VM), alignof(JSC::ThrowScope), alignof(JSC::CatchScope), alignof(FFI__ptr), alignof(Reader__u8), alignof(Reader__u16), alignof(Reader__u32), alignof(Reader__ptr), alignof(Reader__i8), alignof(Reader__i16), alignof(Reader__i32), alignof(Reader__f32), alignof(Reader__f64), alignof(Reader__i64), alignof(Reader__u64), alignof(Reader__intptr), alignof(Crypto__getRandomValues), alignof(Crypto__randomUUID), alignof(Crypto__timingSafeEqual), alignof(Zig::GlobalObject), alignof(Bun__Path), alignof(ArrayBufferSink), alignof(HTTPSResponseSink), alignof(HTTPResponseSink), alignof(FileSink)}; diff --git a/src/bun.js/bindings/headers.h b/src/bun.js/bindings/headers.h index 2d0f567d8..159a7acbd 100644 --- a/src/bun.js/bindings/headers.h +++ b/src/bun.js/bindings/headers.h @@ -1,5 +1,5 @@ // clang-format off -//-- AUTOGENERATED FILE -- 1674546420 +//-- AUTOGENERATED FILE -- 1676266700 #pragma once #include <stddef.h> @@ -55,8 +55,8 @@ typedef void* JSClassRef; typedef bJSC__JSObject JSC__JSObject; // JSC::JSObject typedef WebSocketClient WebSocketClient; typedef WebSocketHTTPSClient WebSocketHTTPSClient; - typedef bJSC__VM JSC__VM; // JSC::VM typedef JSClassRef JSClassRef; + typedef bJSC__VM JSC__VM; // JSC::VM typedef Bun__ArrayBuffer Bun__ArrayBuffer; typedef Uint8Array_alias Uint8Array_alias; typedef WebSocketClientTLS WebSocketClientTLS; @@ -72,6 +72,7 @@ typedef void* JSClassRef; typedef bJSC__JSInternalPromise JSC__JSInternalPromise; // JSC::JSInternalPromise typedef bJSC__Exception JSC__Exception; // JSC::Exception typedef bJSC__JSString JSC__JSString; // JSC::JSString + typedef struct WebCore__DOMFormData WebCore__DOMFormData; // WebCore::DOMFormData typedef struct JSC__CallFrame JSC__CallFrame; // JSC::CallFrame typedef struct WebCore__FetchHeaders WebCore__FetchHeaders; // WebCore::FetchHeaders @@ -92,6 +93,7 @@ typedef void* JSClassRef; class ThrowScope; } namespace WebCore { + class DOMFormData; class DOMURL; class FetchHeaders; } @@ -120,6 +122,7 @@ typedef void* JSClassRef; using JSC__VM = JSC::VM; using JSC__CallFrame = JSC::CallFrame; using JSC__ThrowScope = JSC::ThrowScope; + using WebCore__DOMFormData = WebCore::DOMFormData; using WebCore__DOMURL = WebCore::DOMURL; using WebCore__FetchHeaders = WebCore::FetchHeaders; @@ -146,6 +149,15 @@ CPP_DECL WebCore__DOMURL* WebCore__DOMURL__cast_(JSC__JSValue JSValue0, JSC__VM* CPP_DECL void WebCore__DOMURL__href_(WebCore__DOMURL* arg0, ZigString* arg1); CPP_DECL void WebCore__DOMURL__pathname_(WebCore__DOMURL* arg0, ZigString* arg1); +#pragma mark - WebCore::DOMFormData + +CPP_DECL void WebCore__DOMFormData__append(WebCore__DOMFormData* arg0, ZigString* arg1, ZigString* arg2); +CPP_DECL void WebCore__DOMFormData__appendBlob(WebCore__DOMFormData* arg0, JSC__JSGlobalObject* arg1, ZigString* arg2, void* arg3, ZigString* arg4); +CPP_DECL size_t WebCore__DOMFormData__count(WebCore__DOMFormData* arg0); +CPP_DECL JSC__JSValue WebCore__DOMFormData__create(JSC__JSGlobalObject* arg0); +CPP_DECL JSC__JSValue WebCore__DOMFormData__createFromURLQuery(JSC__JSGlobalObject* arg0, ZigString* arg1); +CPP_DECL WebCore__DOMFormData* WebCore__DOMFormData__fromJS(JSC__JSValue JSValue0); + #pragma mark - WebCore::FetchHeaders CPP_DECL void WebCore__FetchHeaders__append(WebCore__FetchHeaders* arg0, const ZigString* arg1, const ZigString* arg2); diff --git a/src/bun.js/bindings/headers.zig b/src/bun.js/bindings/headers.zig index f28a765fe..756a08bcc 100644 --- a/src/bun.js/bindings/headers.zig +++ b/src/bun.js/bindings/headers.zig @@ -97,6 +97,12 @@ pub extern fn ZigString__toValueGC(arg0: [*c]const ZigString, arg1: *bindings.JS pub extern fn WebCore__DOMURL__cast_(JSValue0: JSC__JSValue, arg1: *bindings.VM) ?*bindings.DOMURL; pub extern fn WebCore__DOMURL__href_(arg0: ?*bindings.DOMURL, arg1: [*c]ZigString) void; pub extern fn WebCore__DOMURL__pathname_(arg0: ?*bindings.DOMURL, arg1: [*c]ZigString) void; +pub extern fn WebCore__DOMFormData__append(arg0: ?*bindings.DOMFormData, arg1: [*c]ZigString, arg2: [*c]ZigString) void; +pub extern fn WebCore__DOMFormData__appendBlob(arg0: ?*bindings.DOMFormData, arg1: *bindings.JSGlobalObject, arg2: [*c]ZigString, arg3: ?*anyopaque, arg4: [*c]ZigString) void; +pub extern fn WebCore__DOMFormData__count(arg0: ?*bindings.DOMFormData) usize; +pub extern fn WebCore__DOMFormData__create(arg0: *bindings.JSGlobalObject) JSC__JSValue; +pub extern fn WebCore__DOMFormData__createFromURLQuery(arg0: *bindings.JSGlobalObject, arg1: [*c]ZigString) JSC__JSValue; +pub extern fn WebCore__DOMFormData__fromJS(JSValue0: JSC__JSValue) ?*bindings.DOMFormData; pub extern fn WebCore__FetchHeaders__append(arg0: ?*bindings.FetchHeaders, arg1: [*c]const ZigString, arg2: [*c]const ZigString) void; pub extern fn WebCore__FetchHeaders__cast_(JSValue0: JSC__JSValue, arg1: *bindings.VM) ?*bindings.FetchHeaders; pub extern fn WebCore__FetchHeaders__clone(arg0: ?*bindings.FetchHeaders, arg1: *bindings.JSGlobalObject) JSC__JSValue; diff --git a/src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h b/src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h index 5b3605354..53b5b6994 100644 --- a/src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h +++ b/src/bun.js/bindings/webcore/DOMClientIsoSubspaces.h @@ -35,8 +35,8 @@ public: /* --- bun --- */ std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForDOMException; - // std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForDOMFormData; - // std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForDOMFormDataIterator; + std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForDOMFormData; + std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForDOMFormDataIterator; std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForDOMURL; std::unique_ptr<GCClient::IsoSubspace> m_clientSubspaceForURLSearchParams; diff --git a/src/bun.js/bindings/webcore/DOMIsoSubspaces.h b/src/bun.js/bindings/webcore/DOMIsoSubspaces.h index 461a63ac6..089d12043 100644 --- a/src/bun.js/bindings/webcore/DOMIsoSubspaces.h +++ b/src/bun.js/bindings/webcore/DOMIsoSubspaces.h @@ -467,8 +467,8 @@ public: // std::unique_ptr<IsoSubspace> m_subspaceForFileList; // std::unique_ptr<IsoSubspace> m_subspaceForFileReader; // std::unique_ptr<IsoSubspace> m_subspaceForFileReaderSync; - // std::unique_ptr<IsoSubspace> m_subspaceForDOMFormData; - // std::unique_ptr<IsoSubspace> m_subspaceForDOMFormDataIterator; + std::unique_ptr<IsoSubspace> m_subspaceForDOMFormData; + std::unique_ptr<IsoSubspace> m_subspaceForDOMFormDataIterator; // std::unique_ptr<IsoSubspace> m_subspaceForDOMTokenList; // std::unique_ptr<IsoSubspace> m_subspaceForDOMTokenListIterator; // std::unique_ptr<IsoSubspace> m_subspaceForDOMURL; diff --git a/src/bun.js/bindings/webcore/JSDOMFormData.cpp b/src/bun.js/bindings/webcore/JSDOMFormData.cpp new file mode 100644 index 000000000..44c28bd00 --- /dev/null +++ b/src/bun.js/bindings/webcore/JSDOMFormData.cpp @@ -0,0 +1,654 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "JSDOMFormData.h" + +#include "ActiveDOMObject.h" +#include "DOMClientIsoSubspaces.h" +#include "DOMIsoSubspaces.h" +#include "IDLTypes.h" +#include "JSDOMBinding.h" +#include "JSDOMConstructor.h" +#include "JSDOMConvertBase.h" +#include "JSDOMConvertBoolean.h" +#include "JSDOMConvertInterface.h" +#include "JSDOMConvertNullable.h" +#include "JSDOMConvertSequences.h" +#include "JSDOMConvertStrings.h" +#include "JSDOMConvertUnion.h" +#include "JSDOMExceptionHandling.h" +#include "JSDOMGlobalObject.h" +#include "JSDOMGlobalObjectInlines.h" +#include "JSDOMIterator.h" +#include "JSDOMOperation.h" +#include "JSDOMWrapperCache.h" +#include "ScriptExecutionContext.h" +#include "WebCoreJSClientData.h" +#include <JavaScriptCore/BuiltinNames.h> +#include <JavaScriptCore/FunctionPrototype.h> +#include <JavaScriptCore/HeapAnalyzer.h> +#include <JavaScriptCore/JSArray.h> +#include <JavaScriptCore/JSCInlines.h> +#include <JavaScriptCore/JSDestructibleObjectHeapCellType.h> +#include <JavaScriptCore/SlotVisitorMacros.h> +#include <JavaScriptCore/SubspaceInlines.h> +#include <variant> +#include <wtf/GetPtr.h> +#include <wtf/PointerPreparations.h> +#include <wtf/URL.h> +#include "ZigGeneratedClasses.h" + +namespace WebCore { +using namespace JSC; + +struct JSBlobWrapperConverter { + static RefPtr<Blob> toWrapped(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue value) + { + auto* globalObject = JSC::jsDynamicCast<JSDOMGlobalObject*>(&lexicalGlobalObject); + if (!globalObject) + return nullptr; + + auto* readableStream = JSC::jsDynamicCast<JSBlob*>(value); + if (!readableStream) + return nullptr; + + return Blob::create(value); + } +}; + +template<> struct JSDOMWrapperConverterTraits<Blob> { + using WrapperClass = JSBlobWrapperConverter; + using ToWrappedReturnType = RefPtr<Blob>; + static constexpr bool needsState = true; +}; + +template<> struct Converter<IDLInterface<Blob>> : DefaultConverter<IDLInterface<Blob>> { + static RefPtr<Blob> convert(JSC::JSGlobalObject& lexicalGlobalObject, JSC::JSValue value, JSDOMGlobalObject& globalObject) + { + return JSBlobWrapperConverter::toWrapped(lexicalGlobalObject, value); + } +}; + +// Functions + +static JSC_DECLARE_HOST_FUNCTION(jsDOMFormDataPrototypeFunction_append); +static JSC_DECLARE_HOST_FUNCTION(jsDOMFormDataPrototypeFunction_delete); +static JSC_DECLARE_HOST_FUNCTION(jsDOMFormDataPrototypeFunction_get); +static JSC_DECLARE_HOST_FUNCTION(jsDOMFormDataPrototypeFunction_getAll); +static JSC_DECLARE_HOST_FUNCTION(jsDOMFormDataPrototypeFunction_has); +static JSC_DECLARE_HOST_FUNCTION(jsDOMFormDataPrototypeFunction_set); +static JSC_DECLARE_HOST_FUNCTION(jsDOMFormDataPrototypeFunction_entries); +static JSC_DECLARE_HOST_FUNCTION(jsDOMFormDataPrototypeFunction_keys); +static JSC_DECLARE_HOST_FUNCTION(jsDOMFormDataPrototypeFunction_values); +static JSC_DECLARE_HOST_FUNCTION(jsDOMFormDataPrototypeFunction_forEach); + +// Attributes + +static JSC_DECLARE_CUSTOM_GETTER(jsDOMFormDataConstructor); + +class JSDOMFormDataPrototype final : public JSC::JSNonFinalObject { +public: + using Base = JSC::JSNonFinalObject; + static JSDOMFormDataPrototype* create(JSC::VM& vm, JSDOMGlobalObject* globalObject, JSC::Structure* structure) + { + JSDOMFormDataPrototype* ptr = new (NotNull, JSC::allocateCell<JSDOMFormDataPrototype>(vm)) JSDOMFormDataPrototype(vm, globalObject, structure); + ptr->finishCreation(vm); + return ptr; + } + + DECLARE_INFO; + template<typename CellType, JSC::SubspaceAccess> + static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSDOMFormDataPrototype, Base); + return &vm.plainObjectSpace(); + } + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + } + +private: + JSDOMFormDataPrototype(JSC::VM& vm, JSC::JSGlobalObject*, JSC::Structure* structure) + : JSC::JSNonFinalObject(vm, structure) + { + } + + void finishCreation(JSC::VM&); +}; +STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSDOMFormDataPrototype, JSDOMFormDataPrototype::Base); + +using JSDOMFormDataDOMConstructor = JSDOMConstructor<JSDOMFormData>; + +template<> EncodedJSValue JSC_HOST_CALL_ATTRIBUTES JSDOMFormDataDOMConstructor::construct(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame) +{ + VM& vm = lexicalGlobalObject->vm(); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto* castedThis = jsCast<JSDOMFormDataDOMConstructor*>(callFrame->jsCallee()); + ASSERT(castedThis); + auto* context = castedThis->scriptExecutionContext(); + if (UNLIKELY(!context)) + return throwConstructorScriptExecutionContextUnavailableError(*lexicalGlobalObject, throwScope, "FormData"); + auto object = DOMFormData::create(context); + if constexpr (IsExceptionOr<decltype(object)>) + RETURN_IF_EXCEPTION(throwScope, {}); + static_assert(TypeOrExceptionOrUnderlyingType<decltype(object)>::isRef); + auto jsValue = toJSNewlyCreated<IDLInterface<DOMFormData>>(*lexicalGlobalObject, *castedThis->globalObject(), throwScope, WTFMove(object)); + if constexpr (IsExceptionOr<decltype(object)>) + RETURN_IF_EXCEPTION(throwScope, {}); + setSubclassStructureIfNeeded<DOMFormData>(lexicalGlobalObject, callFrame, asObject(jsValue)); + RETURN_IF_EXCEPTION(throwScope, {}); + return JSValue::encode(jsValue); +} +JSC_ANNOTATE_HOST_FUNCTION(JSDOMFormDataDOMConstructorConstruct, JSDOMFormDataDOMConstructor::construct); + +template<> const ClassInfo JSDOMFormDataDOMConstructor::s_info = { "FormData"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSDOMFormDataDOMConstructor) }; + +template<> JSValue JSDOMFormDataDOMConstructor::prototypeForStructure(JSC::VM& vm, const JSDOMGlobalObject& globalObject) +{ + UNUSED_PARAM(vm); + return globalObject.functionPrototype(); +} + +template<> void JSDOMFormDataDOMConstructor::initializeProperties(VM& vm, JSDOMGlobalObject& globalObject) +{ + putDirect(vm, vm.propertyNames->length, jsNumber(0), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum); + JSString* nameString = jsNontrivialString(vm, "FormData"_s); + m_originalName.set(vm, this, nameString); + putDirect(vm, vm.propertyNames->name, nameString, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum); + putDirect(vm, vm.propertyNames->prototype, JSDOMFormData::prototype(vm, globalObject), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete); +} + +/* Hash table for prototype */ + +static const HashTableValue JSDOMFormDataPrototypeTableValues[] = { + { "constructor"_s, static_cast<unsigned>(JSC::PropertyAttribute::DontEnum), NoIntrinsic, { HashTableValue::GetterSetterType, jsDOMFormDataConstructor, 0 } }, + { "append"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsDOMFormDataPrototypeFunction_append, 2 } }, + { "delete"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsDOMFormDataPrototypeFunction_delete, 1 } }, + { "get"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsDOMFormDataPrototypeFunction_get, 1 } }, + { "getAll"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsDOMFormDataPrototypeFunction_getAll, 1 } }, + { "has"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsDOMFormDataPrototypeFunction_has, 1 } }, + { "set"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsDOMFormDataPrototypeFunction_set, 2 } }, + { "entries"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsDOMFormDataPrototypeFunction_entries, 0 } }, + { "keys"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsDOMFormDataPrototypeFunction_keys, 0 } }, + { "values"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsDOMFormDataPrototypeFunction_values, 0 } }, + { "forEach"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function), NoIntrinsic, { HashTableValue::NativeFunctionType, jsDOMFormDataPrototypeFunction_forEach, 1 } }, +}; + +const ClassInfo JSDOMFormDataPrototype::s_info = { "FormData"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSDOMFormDataPrototype) }; + +void JSDOMFormDataPrototype::finishCreation(VM& vm) +{ + Base::finishCreation(vm); + reifyStaticProperties(vm, JSDOMFormData::info(), JSDOMFormDataPrototypeTableValues, *this); + putDirect(vm, vm.propertyNames->iteratorSymbol, getDirect(vm, vm.propertyNames->builtinNames().entriesPublicName()), static_cast<unsigned>(JSC::PropertyAttribute::DontEnum)); + JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); +} + +const ClassInfo JSDOMFormData::s_info = { "FormData"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSDOMFormData) }; + +JSDOMFormData::JSDOMFormData(Structure* structure, JSDOMGlobalObject& globalObject, Ref<DOMFormData>&& impl) + : JSDOMWrapper<DOMFormData>(structure, globalObject, WTFMove(impl)) +{ +} + +void JSDOMFormData::finishCreation(VM& vm) +{ + Base::finishCreation(vm); + ASSERT(inherits(info())); + + // static_assert(!std::is_base_of<ActiveDOMObject, DOMFormData>::value, "Interface is not marked as [ActiveDOMObject] even though implementation class subclasses ActiveDOMObject."); +} + +JSObject* JSDOMFormData::createPrototype(VM& vm, JSDOMGlobalObject& globalObject) +{ + return JSDOMFormDataPrototype::create(vm, &globalObject, JSDOMFormDataPrototype::createStructure(vm, &globalObject, globalObject.objectPrototype())); +} + +JSObject* JSDOMFormData::prototype(VM& vm, JSDOMGlobalObject& globalObject) +{ + return getDOMPrototype<JSDOMFormData>(vm, globalObject); +} + +JSValue JSDOMFormData::getConstructor(VM& vm, const JSGlobalObject* globalObject) +{ + return getDOMConstructor<JSDOMFormDataDOMConstructor, DOMConstructorID::DOMFormData>(vm, *jsCast<const JSDOMGlobalObject*>(globalObject)); +} + +void JSDOMFormData::destroy(JSC::JSCell* cell) +{ + JSDOMFormData* thisObject = static_cast<JSDOMFormData*>(cell); + thisObject->JSDOMFormData::~JSDOMFormData(); +} + +JSC_DEFINE_CUSTOM_GETTER(jsDOMFormDataConstructor, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName)) +{ + VM& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + auto* prototype = jsDynamicCast<JSDOMFormDataPrototype*>(JSValue::decode(thisValue)); + if (UNLIKELY(!prototype)) + return throwVMTypeError(lexicalGlobalObject, throwScope); + return JSValue::encode(JSDOMFormData::getConstructor(JSC::getVM(lexicalGlobalObject), prototype->globalObject())); +} + +static inline JSC::EncodedJSValue jsDOMFormDataPrototypeFunction_append1Body(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSDOMFormData>::ClassParameter castedThis) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + auto& impl = castedThis->wrapped(); + EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); + auto name = convert<IDLUSVString>(*lexicalGlobalObject, argument0.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); + auto value = convert<IDLUSVString>(*lexicalGlobalObject, argument1.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLUndefined>(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.append(WTFMove(name), WTFMove(value)); }))); +} + +static inline JSC::EncodedJSValue jsDOMFormDataPrototypeFunction_append2Body(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSDOMFormData>::ClassParameter castedThis) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + auto& impl = castedThis->wrapped(); + EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); + auto name = convert<IDLUSVString>(*lexicalGlobalObject, argument0.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); + + EnsureStillAliveScope argument2 = callFrame->argument(2); + auto filename = argument2.value().isUndefined() ? String() : convert<IDLUSVString>(*lexicalGlobalObject, argument2.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + + RefPtr<Blob> blobValue = nullptr; + if (argument1.value().inherits<JSBlob>()) { + blobValue = Blob::create(argument1.value()); + } + + if (!blobValue) { + throwTypeError(lexicalGlobalObject, throwScope, "Expected argument to be a Blob."_s); + } + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLUndefined>(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.append(WTFMove(name), WTFMove(blobValue), WTFMove(filename)); }))); +} + +static inline JSC::EncodedJSValue jsDOMFormDataPrototypeFunction_appendOverloadDispatcher(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSDOMFormData>::ClassParameter castedThis) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + size_t argsCount = std::min<size_t>(3, callFrame->argumentCount()); + if (argsCount == 2) { + JSValue distinguishingArg = callFrame->uncheckedArgument(1); + if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits<JSBlob>()) + RELEASE_AND_RETURN(throwScope, (jsDOMFormDataPrototypeFunction_append2Body(lexicalGlobalObject, callFrame, castedThis))); + RELEASE_AND_RETURN(throwScope, (jsDOMFormDataPrototypeFunction_append1Body(lexicalGlobalObject, callFrame, castedThis))); + } + if (argsCount == 3) { + RELEASE_AND_RETURN(throwScope, (jsDOMFormDataPrototypeFunction_append2Body(lexicalGlobalObject, callFrame, castedThis))); + } + return argsCount < 2 ? throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)) : throwVMTypeError(lexicalGlobalObject, throwScope); +} + +JSC_DEFINE_HOST_FUNCTION(jsDOMFormDataPrototypeFunction_append, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperation<JSDOMFormData>::call<jsDOMFormDataPrototypeFunction_appendOverloadDispatcher>(*lexicalGlobalObject, *callFrame, "append"); +} + +static inline JSC::EncodedJSValue jsDOMFormDataPrototypeFunction_deleteBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSDOMFormData>::ClassParameter castedThis) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + auto& impl = castedThis->wrapped(); + if (UNLIKELY(callFrame->argumentCount() < 1)) + return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); + EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); + auto name = convert<IDLUSVString>(*lexicalGlobalObject, argument0.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLUndefined>(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.remove(WTFMove(name)); }))); +} + +JSC_DEFINE_HOST_FUNCTION(jsDOMFormDataPrototypeFunction_delete, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperation<JSDOMFormData>::call<jsDOMFormDataPrototypeFunction_deleteBody>(*lexicalGlobalObject, *callFrame, "delete"); +} + +static inline JSC::EncodedJSValue jsDOMFormDataPrototypeFunction_getBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSDOMFormData>::ClassParameter castedThis) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + auto& impl = castedThis->wrapped(); + if (UNLIKELY(callFrame->argumentCount() < 1)) + return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); + EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); + auto name = convert<IDLUSVString>(*lexicalGlobalObject, argument0.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLNullable<IDLUnion<IDLUSVString, IDLInterface<Blob>>>>(*lexicalGlobalObject, *castedThis->globalObject(), throwScope, impl.get(WTFMove(name))))); +} + +JSC_DEFINE_HOST_FUNCTION(jsDOMFormDataPrototypeFunction_get, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperation<JSDOMFormData>::call<jsDOMFormDataPrototypeFunction_getBody>(*lexicalGlobalObject, *callFrame, "get"); +} + +static inline JSC::EncodedJSValue jsDOMFormDataPrototypeFunction_getAllBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSDOMFormData>::ClassParameter castedThis) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + auto& impl = castedThis->wrapped(); + if (UNLIKELY(callFrame->argumentCount() < 1)) + return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); + EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); + auto name = convert<IDLUSVString>(*lexicalGlobalObject, argument0.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + auto entries = impl.getAll(WTFMove(name)); + JSC::JSArray* result = JSC::constructEmptyArray(lexicalGlobalObject, nullptr, 0); + for (auto entry : entries) { + if (auto string = std::get_if<String>(&entry)) { + result->push(lexicalGlobalObject, jsString(vm, *string)); + } else { + auto blob = std::get<RefPtr<Blob>>(entry); + result->push(lexicalGlobalObject, toJS(lexicalGlobalObject, castedThis->globalObject(), blob.get())); + } + } + + RELEASE_AND_RETURN(throwScope, JSValue::encode(result)); +} + +JSC_DEFINE_HOST_FUNCTION(jsDOMFormDataPrototypeFunction_getAll, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperation<JSDOMFormData>::call<jsDOMFormDataPrototypeFunction_getAllBody>(*lexicalGlobalObject, *callFrame, "getAll"); +} + +static inline JSC::EncodedJSValue jsDOMFormDataPrototypeFunction_hasBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSDOMFormData>::ClassParameter castedThis) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + auto& impl = castedThis->wrapped(); + if (UNLIKELY(callFrame->argumentCount() < 1)) + return throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)); + EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); + auto name = convert<IDLUSVString>(*lexicalGlobalObject, argument0.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLBoolean>(*lexicalGlobalObject, throwScope, impl.has(WTFMove(name))))); +} + +JSC_DEFINE_HOST_FUNCTION(jsDOMFormDataPrototypeFunction_has, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperation<JSDOMFormData>::call<jsDOMFormDataPrototypeFunction_hasBody>(*lexicalGlobalObject, *callFrame, "has"); +} + +static inline JSC::EncodedJSValue jsDOMFormDataPrototypeFunction_set1Body(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSDOMFormData>::ClassParameter castedThis) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + auto& impl = castedThis->wrapped(); + EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); + auto name = convert<IDLUSVString>(*lexicalGlobalObject, argument0.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); + auto value = convert<IDLUSVString>(*lexicalGlobalObject, argument1.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLUndefined>(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.set(WTFMove(name), WTFMove(value)); }))); +} + +static inline JSC::EncodedJSValue jsDOMFormDataPrototypeFunction_set2Body(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSDOMFormData>::ClassParameter castedThis) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + auto& impl = castedThis->wrapped(); + EnsureStillAliveScope argument0 = callFrame->uncheckedArgument(0); + auto name = convert<IDLUSVString>(*lexicalGlobalObject, argument0.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + EnsureStillAliveScope argument1 = callFrame->uncheckedArgument(1); + + EnsureStillAliveScope argument2 = callFrame->argument(2); + auto filename = argument2.value().isUndefined() ? String() : convert<IDLUSVString>(*lexicalGlobalObject, argument2.value()); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + + RefPtr<Blob> blobValue = nullptr; + if (argument1.value().inherits<JSBlob>()) { + blobValue = Blob::create(argument1.value()); + } + + if (!blobValue) { + throwTypeError(lexicalGlobalObject, throwScope, "Expected argument to be a Blob."_s); + RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); + } + + RELEASE_AND_RETURN(throwScope, JSValue::encode(toJS<IDLUndefined>(*lexicalGlobalObject, throwScope, [&]() -> decltype(auto) { return impl.set(WTFMove(name), WTFMove(blobValue), WTFMove(filename)); }))); +} + +static inline JSC::EncodedJSValue jsDOMFormDataPrototypeFunction_setOverloadDispatcher(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSDOMFormData>::ClassParameter castedThis) +{ + auto& vm = JSC::getVM(lexicalGlobalObject); + auto throwScope = DECLARE_THROW_SCOPE(vm); + UNUSED_PARAM(throwScope); + UNUSED_PARAM(callFrame); + size_t argsCount = std::min<size_t>(3, callFrame->argumentCount()); + if (argsCount == 2) { + JSValue distinguishingArg = callFrame->uncheckedArgument(1); + if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits<JSBlob>()) + RELEASE_AND_RETURN(throwScope, (jsDOMFormDataPrototypeFunction_set2Body(lexicalGlobalObject, callFrame, castedThis))); + RELEASE_AND_RETURN(throwScope, (jsDOMFormDataPrototypeFunction_set1Body(lexicalGlobalObject, callFrame, castedThis))); + } + if (argsCount == 3) { + RELEASE_AND_RETURN(throwScope, (jsDOMFormDataPrototypeFunction_set2Body(lexicalGlobalObject, callFrame, castedThis))); + } + return argsCount < 2 ? throwVMError(lexicalGlobalObject, throwScope, createNotEnoughArgumentsError(lexicalGlobalObject)) : throwVMTypeError(lexicalGlobalObject, throwScope); +} + +JSC_DEFINE_HOST_FUNCTION(jsDOMFormDataPrototypeFunction_set, (JSGlobalObject * lexicalGlobalObject, CallFrame* callFrame)) +{ + return IDLOperation<JSDOMFormData>::call<jsDOMFormDataPrototypeFunction_setOverloadDispatcher>(*lexicalGlobalObject, *callFrame, "set"); +} + +struct DOMFormDataIteratorTraits { + static constexpr JSDOMIteratorType type = JSDOMIteratorType::Map; + using KeyType = IDLUSVString; + using ValueType = IDLUnion<IDLUSVString, IDLInterface<Blob>>; +}; + +using DOMFormDataIteratorBase = JSDOMIteratorBase<JSDOMFormData, DOMFormDataIteratorTraits>; +class DOMFormDataIterator final : public DOMFormDataIteratorBase { +public: + using Base = DOMFormDataIteratorBase; + DECLARE_INFO; + + template<typename, SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return WebCore::subspaceForImpl<DOMFormDataIterator, UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForDOMFormDataIterator.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForDOMFormDataIterator = std::forward<decltype(space)>(space); }, + [](auto& spaces) { return spaces.m_subspaceForDOMFormDataIterator.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForDOMFormDataIterator = std::forward<decltype(space)>(space); }); + } + + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info()); + } + + static DOMFormDataIterator* create(JSC::VM& vm, JSC::Structure* structure, JSDOMFormData& iteratedObject, IterationKind kind) + { + auto* instance = new (NotNull, JSC::allocateCell<DOMFormDataIterator>(vm)) DOMFormDataIterator(structure, iteratedObject, kind); + instance->finishCreation(vm); + return instance; + } + +private: + DOMFormDataIterator(JSC::Structure* structure, JSDOMFormData& iteratedObject, IterationKind kind) + : Base(structure, iteratedObject, kind) + { + } +}; + +using DOMFormDataIteratorPrototype = JSDOMIteratorPrototype<JSDOMFormData, DOMFormDataIteratorTraits>; +JSC_ANNOTATE_HOST_FUNCTION(DOMFormDataIteratorPrototypeNext, DOMFormDataIteratorPrototype::next); + +template<> +const JSC::ClassInfo DOMFormDataIteratorBase::s_info = { "FormDataBase Iterator"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(DOMFormDataIteratorBase) }; +const JSC::ClassInfo DOMFormDataIterator::s_info = { "FormData Iterator"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(DOMFormDataIterator) }; + +template<> +const JSC::ClassInfo DOMFormDataIteratorPrototype::s_info = { "FormData Iterator"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(DOMFormDataIteratorPrototype) }; + +static inline EncodedJSValue jsDOMFormDataPrototypeFunction_entriesCaller(JSGlobalObject*, CallFrame*, JSDOMFormData* thisObject) +{ + return JSValue::encode(iteratorCreate<DOMFormDataIterator>(*thisObject, IterationKind::Entries)); +} + +JSC_DEFINE_HOST_FUNCTION(jsDOMFormDataPrototypeFunction_entries, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) +{ + return IDLOperation<JSDOMFormData>::call<jsDOMFormDataPrototypeFunction_entriesCaller>(*lexicalGlobalObject, *callFrame, "entries"); +} + +static inline EncodedJSValue jsDOMFormDataPrototypeFunction_keysCaller(JSGlobalObject*, CallFrame*, JSDOMFormData* thisObject) +{ + return JSValue::encode(iteratorCreate<DOMFormDataIterator>(*thisObject, IterationKind::Keys)); +} + +JSC_DEFINE_HOST_FUNCTION(jsDOMFormDataPrototypeFunction_keys, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) +{ + return IDLOperation<JSDOMFormData>::call<jsDOMFormDataPrototypeFunction_keysCaller>(*lexicalGlobalObject, *callFrame, "keys"); +} + +static inline EncodedJSValue jsDOMFormDataPrototypeFunction_valuesCaller(JSGlobalObject*, CallFrame*, JSDOMFormData* thisObject) +{ + return JSValue::encode(iteratorCreate<DOMFormDataIterator>(*thisObject, IterationKind::Values)); +} + +JSC_DEFINE_HOST_FUNCTION(jsDOMFormDataPrototypeFunction_values, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) +{ + return IDLOperation<JSDOMFormData>::call<jsDOMFormDataPrototypeFunction_valuesCaller>(*lexicalGlobalObject, *callFrame, "values"); +} + +static inline EncodedJSValue jsDOMFormDataPrototypeFunction_forEachCaller(JSGlobalObject* lexicalGlobalObject, CallFrame* callFrame, JSDOMFormData* thisObject) +{ + return JSValue::encode(iteratorForEach<DOMFormDataIterator>(*lexicalGlobalObject, *callFrame, *thisObject)); +} + +JSC_DEFINE_HOST_FUNCTION(jsDOMFormDataPrototypeFunction_forEach, (JSC::JSGlobalObject * lexicalGlobalObject, JSC::CallFrame* callFrame)) +{ + return IDLOperation<JSDOMFormData>::call<jsDOMFormDataPrototypeFunction_forEachCaller>(*lexicalGlobalObject, *callFrame, "forEach"); +} + +JSC::GCClient::IsoSubspace* JSDOMFormData::subspaceForImpl(JSC::VM& vm) +{ + return WebCore::subspaceForImpl<JSDOMFormData, UseCustomHeapCellType::No>( + vm, + [](auto& spaces) { return spaces.m_clientSubspaceForDOMFormData.get(); }, + [](auto& spaces, auto&& space) { spaces.m_clientSubspaceForDOMFormData = std::forward<decltype(space)>(space); }, + [](auto& spaces) { return spaces.m_subspaceForDOMFormData.get(); }, + [](auto& spaces, auto&& space) { spaces.m_subspaceForDOMFormData = std::forward<decltype(space)>(space); }); +} + +void JSDOMFormData::analyzeHeap(JSCell* cell, HeapAnalyzer& analyzer) +{ + auto* thisObject = jsCast<JSDOMFormData*>(cell); + analyzer.setWrappedObjectForCell(cell, &thisObject->wrapped()); + if (thisObject->scriptExecutionContext()) + analyzer.setLabelForCell(cell, "url " + thisObject->scriptExecutionContext()->url().string()); + Base::analyzeHeap(cell, analyzer); +} + +bool JSDOMFormDataOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, AbstractSlotVisitor& visitor, const char** reason) +{ + UNUSED_PARAM(handle); + UNUSED_PARAM(visitor); + UNUSED_PARAM(reason); + return false; +} + +void JSDOMFormDataOwner::finalize(JSC::Handle<JSC::Unknown> handle, void* context) +{ + auto* jsDOMFormData = static_cast<JSDOMFormData*>(handle.slot()->asCell()); + auto& world = *static_cast<DOMWrapperWorld*>(context); + uncacheWrapper(world, &jsDOMFormData->wrapped(), jsDOMFormData); +} + +#if ENABLE(BINDING_INTEGRITY) +#if PLATFORM(WIN) +#pragma warning(disable : 4483) +extern "C" { +extern void (*const __identifier("??_7DOMFormData@WebCore@@6B@")[])(); +} +#else +extern "C" { +extern void* _ZTVN7WebCore11DOMFormDataE[]; +} +#endif +#endif + +JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject* globalObject, Ref<DOMFormData>&& impl) +{ + + if constexpr (std::is_polymorphic_v<DOMFormData>) { +#if ENABLE(BINDING_INTEGRITY) + const void* actualVTablePointer = getVTablePointer(impl.ptr()); +#if PLATFORM(WIN) + void* expectedVTablePointer = __identifier("??_7DOMFormData@WebCore@@6B@"); +#else + void* expectedVTablePointer = &_ZTVN7WebCore11DOMFormDataE[2]; +#endif + + // If you hit this assertion you either have a use after free bug, or + // DOMFormData has subclasses. If DOMFormData has subclasses that get passed + // to toJS() we currently require DOMFormData you to opt out of binding hardening + // by adding the SkipVTableValidation attribute to the interface IDL definition + RELEASE_ASSERT(actualVTablePointer == expectedVTablePointer); +#endif + } + return createWrapper<DOMFormData>(globalObject, WTFMove(impl)); +} + +JSC::JSValue toJS(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, DOMFormData& impl) +{ + return wrap(lexicalGlobalObject, globalObject, impl); +} + +DOMFormData* JSDOMFormData::toWrapped(JSC::VM&, JSC::JSValue value) +{ + if (auto* wrapper = jsDynamicCast<JSDOMFormData*>(value)) + return &wrapper->wrapped(); + return nullptr; +} +} diff --git a/src/bun.js/bindings/webcore/JSDOMFormData.dep b/src/bun.js/bindings/webcore/JSDOMFormData.dep new file mode 100644 index 000000000..5757aa3ae --- /dev/null +++ b/src/bun.js/bindings/webcore/JSDOMFormData.dep @@ -0,0 +1 @@ +JSDOMFormData.h : diff --git a/src/bun.js/bindings/webcore/JSDOMFormData.h b/src/bun.js/bindings/webcore/JSDOMFormData.h new file mode 100644 index 000000000..085c42c5d --- /dev/null +++ b/src/bun.js/bindings/webcore/JSDOMFormData.h @@ -0,0 +1,93 @@ +/* + This file is part of the WebKit open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#pragma once + +#include "DOMFormData.h" +#include "JSDOMWrapper.h" +#include <wtf/NeverDestroyed.h> + +namespace WebCore { + +class JSDOMFormData : public JSDOMWrapper<DOMFormData> { +public: + using Base = JSDOMWrapper<DOMFormData>; + static JSDOMFormData* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject, Ref<DOMFormData>&& impl) + { + JSDOMFormData* ptr = new (NotNull, JSC::allocateCell<JSDOMFormData>(globalObject->vm())) JSDOMFormData(structure, *globalObject, WTFMove(impl)); + ptr->finishCreation(globalObject->vm()); + return ptr; + } + + static JSC::JSObject* createPrototype(JSC::VM&, JSDOMGlobalObject&); + static JSC::JSObject* prototype(JSC::VM&, JSDOMGlobalObject&); + static DOMFormData* toWrapped(JSC::VM&, JSC::JSValue); + static void destroy(JSC::JSCell*); + + DECLARE_INFO; + + static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) + { + return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info(), JSC::NonArray); + } + + static JSC::JSValue getConstructor(JSC::VM&, const JSC::JSGlobalObject*); + template<typename, JSC::SubspaceAccess mode> static JSC::GCClient::IsoSubspace* subspaceFor(JSC::VM& vm) + { + if constexpr (mode == JSC::SubspaceAccess::Concurrently) + return nullptr; + return subspaceForImpl(vm); + } + static JSC::GCClient::IsoSubspace* subspaceForImpl(JSC::VM& vm); + static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&); +protected: + JSDOMFormData(JSC::Structure*, JSDOMGlobalObject&, Ref<DOMFormData>&&); + + void finishCreation(JSC::VM&); +}; + +class JSDOMFormDataOwner final : public JSC::WeakHandleOwner { +public: + bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::AbstractSlotVisitor&, const char**) final; + void finalize(JSC::Handle<JSC::Unknown>, void* context) final; +}; + +inline JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld&, DOMFormData*) +{ + static NeverDestroyed<JSDOMFormDataOwner> owner; + return &owner.get(); +} + +inline void* wrapperKey(DOMFormData* wrappableObject) +{ + return wrappableObject; +} + +JSC::JSValue toJS(JSC::JSGlobalObject*, JSDOMGlobalObject*, DOMFormData&); +inline JSC::JSValue toJS(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, DOMFormData* impl) { return impl ? toJS(lexicalGlobalObject, globalObject, *impl) : JSC::jsNull(); } +JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject*, JSDOMGlobalObject*, Ref<DOMFormData>&&); +inline JSC::JSValue toJSNewlyCreated(JSC::JSGlobalObject* lexicalGlobalObject, JSDOMGlobalObject* globalObject, RefPtr<DOMFormData>&& impl) { return impl ? toJSNewlyCreated(lexicalGlobalObject, globalObject, impl.releaseNonNull()) : JSC::jsNull(); } + +template<> struct JSDOMWrapperConverterTraits<DOMFormData> { + using WrapperClass = JSDOMFormData; + using ToWrappedReturnType = DOMFormData*; +}; + +} // namespace WebCore |