-
-
Notifications
You must be signed in to change notification settings - Fork 124
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement FormData. #645
base: main
Are you sure you want to change the base?
Implement FormData. #645
Changes from 13 commits
b5a24b1
b2503c8
31dc722
34d052d
4147473
2b905f0
e9e3ad1
e636e5b
899a999
9b83d47
4b76a7f
33599a9
0794ca7
44e348c
6e92ba5
28ea9cd
aa20701
8c70bdf
abbda0d
4eacd2f
fa95d18
c6bac30
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
/* | ||
* Copyright (C) 2022-present The WebF authors. All rights reserved. | ||
*/ | ||
|
||
#include "form_data.h" | ||
#include <memory> | ||
#include "bindings/qjs/atomic_string.h" | ||
#include "core/api/form_data_part.h" | ||
#include "core/executing_context.h" | ||
#include "core/fileapi/blob_part.h" | ||
|
||
namespace webf { | ||
const char* className= "FormData"; | ||
FormData* FormData::Create(ExecutingContext* context, ExceptionState& exception_state) { | ||
return MakeGarbageCollected<FormData>(context->ctx()); | ||
} | ||
|
||
FormData::FormData(ExecutingContext* context, NativeBindingObject* native_binding_object) | ||
: BindingObject(context->ctx(), native_binding_object) {} | ||
|
||
NativeValue FormData::HandleCallFromDartSide(const AtomicString& method, | ||
int32_t argc, | ||
const NativeValue* argv, | ||
Dart_Handle dart_object) { | ||
return Native_NewNull(); | ||
} | ||
|
||
bool FormData::IsFormData() const { | ||
return true; | ||
} | ||
|
||
void FormData::append(const AtomicString& name, | ||
const std::shared_ptr<BlobPart>& value, | ||
const AtomicString& fileName, | ||
ExceptionState& exception_state) { | ||
if (name.IsEmpty()) { | ||
exception_state.ThrowException(ctx(), ErrorType::ArgumentError, "The name parameter must not be empty."); | ||
return; | ||
} | ||
|
||
auto form_data_part = std::make_shared<FormDataPart>(name.ToStdString(ctx()), value, fileName.ToStdString(ctx())); | ||
|
||
_parts.push_back(form_data_part); | ||
} | ||
|
||
void FormData::form_data_delete(const AtomicString& name, ExceptionState& exception_state) { | ||
if (name.IsEmpty()) { | ||
exception_state.ThrowException(ctx(), ErrorType::ArgumentError, "The name parameter must not be empty."); | ||
return; | ||
} | ||
|
||
_parts.erase(std::remove_if(_parts.begin(), _parts.end(), | ||
[name, this](const std::shared_ptr<FormDataPart>& part) { | ||
return part->GetName() == name.ToStdString(ctx()); | ||
}), | ||
_parts.end()); | ||
} | ||
|
||
webf::BlobPart* FormData::get(const AtomicString& name, ExceptionState& exception_state) { | ||
if (name.IsEmpty()) { | ||
exception_state.ThrowException(ctx(), ErrorType::ArgumentError, "The name parameter must not be empty."); | ||
return nullptr; | ||
} | ||
|
||
for (const auto& part : _parts) { | ||
if (part->GetName() == name.ToStdString(ctx())) { | ||
return &*part->getFirst(); | ||
} | ||
} | ||
|
||
return nullptr; | ||
} | ||
|
||
std::vector<BlobPart::ImplType> FormData::getAll(const AtomicString& name, ExceptionState& exception_state) { | ||
std::vector<BlobPart::ImplType> result; | ||
|
||
if (name.IsEmpty()) { | ||
exception_state.ThrowException(ctx(), ErrorType::ArgumentError, "The name parameter must not be empty."); | ||
return result; | ||
} | ||
|
||
for (const auto& part : _parts) { | ||
if (part->GetName() == name.ToStdString(ctx())) { | ||
for (const auto& value : part->GetValues()) { | ||
result.push_back(std::make_shared<BlobPart>(value)); | ||
} | ||
} | ||
} | ||
|
||
return result; | ||
} | ||
|
||
bool FormData::has(const AtomicString& name, ExceptionState& exception_state) { | ||
if (name.IsEmpty()) { | ||
exception_state.ThrowException(ctx(), ErrorType::ArgumentError, "The name parameter must not be empty."); | ||
return false; | ||
} | ||
|
||
for (const auto& part : _parts) { | ||
if (part->GetName() == name.ToStdString(ctx())) { | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
void FormData::set(const AtomicString& name, | ||
const std::shared_ptr<webf::BlobPart>& value, | ||
const AtomicString& fileName, | ||
ExceptionState& exception_state) { | ||
if (name.IsEmpty()) { | ||
exception_state.ThrowException(ctx(), ErrorType::ArgumentError, "The name parameter must not be empty."); | ||
return; | ||
} | ||
|
||
_parts.erase(std::remove_if(_parts.begin(), _parts.end(), | ||
[name, this](const std::shared_ptr<FormDataPart>& part) { | ||
return part->GetName() == name.ToStdString(ctx()); | ||
}), | ||
_parts.end()); | ||
|
||
auto form_data_part = std::make_shared<FormDataPart>(name.ToStdString(ctx()), value, fileName.ToStdString(ctx())); | ||
|
||
_parts.push_back(form_data_part); | ||
} | ||
|
||
void FormData::forEach(const std::shared_ptr<QJSFunction>& callback, | ||
const ScriptValue& thisArg, | ||
ExceptionState& exception_state) { | ||
if (!callback || !callback->IsFunction(ctx())) { | ||
exception_state.ThrowException(ctx(), ErrorType::ArgumentError, "The callback function must be callable."); | ||
return; | ||
} | ||
// callbackFn:(value: BlobPart, key: string, parent: FormData) => void | ||
for (const auto& part : _parts) { | ||
ScriptValue args[3]; | ||
/*value*/ args[0] = ScriptValue(ctx(), part->ToQuickJS(ctx())); | ||
/*key*/ args[1] = ScriptValue(ctx(), AtomicString(ctx(), part->GetName())); | ||
|
||
// TODO: which parent??? | ||
/*parent*/ args[2] = ScriptValue(ctx(), this->ToQuickJS()); | ||
|
||
ScriptValue result = callback->Invoke(ctx(), thisArg, 3, args); | ||
if (result.IsException()) { | ||
exception_state.ThrowException(ctx(), result.QJSValue()); | ||
return; | ||
} | ||
} | ||
} | ||
|
||
std::vector<webf::AtomicString> FormData::keys(ExceptionState& exception_state) const { | ||
std::vector<webf::AtomicString> keys; | ||
for (const auto& part : _parts) { | ||
keys.push_back(AtomicString(ctx(), part->GetName())); | ||
} | ||
return keys; | ||
} | ||
|
||
std::vector<std::shared_ptr<BlobPart>> FormData::values(ExceptionState& exception_state) const { | ||
std::vector<std::shared_ptr<BlobPart>> values; | ||
for (const auto& part : _parts) { | ||
for (const auto& value : part->GetValues()) { | ||
values.push_back(std::make_shared<BlobPart>(value)); | ||
} | ||
} | ||
return values; | ||
} | ||
|
||
std::vector<std::shared_ptr<FormDataPart>> FormData::entries(ExceptionState& exception_state) const { | ||
return std::vector<std::shared_ptr<FormDataPart>>(_parts.begin(), _parts.end()); | ||
} | ||
} // namespace webf |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
/* | ||
* Copyright (C) 2022-present The WebF authors. All rights reserved. | ||
*/ | ||
|
||
|
||
// This file is for generate binding code only. | ||
|
||
type FormDataPart={} // dummy code. Real one is introduced in C++ form_data_part.h, also blob_part.h | ||
export interface FormData { | ||
new():FormData; | ||
append(name: string, value: BlobPart, fileName?: string): void; | ||
// This method name is a placeholder of **delete** method to avoid using C++ keyword | ||
// and will be replaced to **delete** when installing in MemberInstaller::InstallFunctions. | ||
form_data_delete(name: string): void; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. unknown API There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. append: https://developer.mozilla.org/en-US/docs/Web/API/FormData/append "delete" is renamed to "form_data_delete" here to avoid using C++ keyword, otherwise will cause a keyword conflict in generated C++ binding code. It will be renamed back to "delete" when register into qjs , see: MemberInstaller::InstallFunctions |
||
get(name: string): BlobPart | ||
getAll(name: string): BlobPart[]; | ||
has(name: string): boolean; | ||
set(name: string, value: BlobPart, fileName?: string): void; | ||
forEach(callbackfn: Function, thisArg?: any): void; | ||
linsmod marked this conversation as resolved.
Show resolved
Hide resolved
|
||
keys():string[] | ||
values():BlobPart[] | ||
entries():FormDataPart[] | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BlobPart支持两者,而且内部也可以区分,似乎不必要创建两个函数?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
重载需要写两个,这样生成器也会生成两个重载,来应对不同的参数传递方式