Skip to content
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

Open
wants to merge 22 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.vscode
.history
.cache
*.log
*.apk
*.ap_
Expand Down Expand Up @@ -48,6 +49,8 @@ build/
*~
*.swp

**/vendor/**

# NDK
obj/
yarn.lock
Expand Down
9 changes: 9 additions & 0 deletions bridge/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,8 @@ if ($ENV{WEBF_JS_ENGINE} MATCHES "quickjs")
bindings/qjs/exception_state.cc
bindings/qjs/exception_message.cc
bindings/qjs/rejected_promises.cc
bindings/qjs/sync_iterator.cc
bindings/qjs/iterable.cc
bindings/qjs/union_base.cc
# Core sources
webf_bridge.cc
Expand Down Expand Up @@ -378,6 +380,9 @@ if ($ENV{WEBF_JS_ENGINE} MATCHES "quickjs")
core/html/forms/html_input_element.cc
core/html/forms/html_form_element.cc
core/html/forms/html_textarea_element.cc
core/html/forms/form_data.cc

# core/platform/network/form_data_encoder.cc

# SVG files
core/svg/svg_element.cc
Expand Down Expand Up @@ -412,6 +417,7 @@ if ($ENV{WEBF_JS_ENGINE} MATCHES "quickjs")
out/qjs_window.cc
out/qjs_location.cc
out/qjs_blob.cc
out/qjs_form_data.cc
out/qjs_event.cc
out/qjs_add_event_listener_options.cc
out/qjs_event_listener_options.cc
Expand Down Expand Up @@ -496,6 +502,7 @@ if ($ENV{WEBF_JS_ENGINE} MATCHES "quickjs")
out/qjs_html_iframe_element.cc
out/qjs_html_canvas_element.cc
out/qjs_html_link_element.cc
out/qjs_module_manager_options.cc
out/qjs_image.cc
out/qjs_widget_element.cc
out/qjs_canvas_rendering_context_2d.cc
Expand All @@ -507,6 +514,7 @@ if ($ENV{WEBF_JS_ENGINE} MATCHES "quickjs")
out/qjs_union_dom_string_sequencedouble.cc
out/qjs_unionhtml_image_elementhtml_canvas_element.cc
out/qjs_union_dom_stringcanvas_gradient.cc
out/qjs_union_dom_stringblob.cc
out/canvas_types.cc
out/qjs_html_button_element.cc
out/qjs_html_input_element.cc
Expand Down Expand Up @@ -554,6 +562,7 @@ if ($ENV{WEBF_JS_ENGINE} MATCHES "quickjs")
out/qjs_svg_ellipse_element.cc
out/qjs_svg_style_element.cc
out/qjs_svg_line_element.cc
out/qjs_sync_iterator.cc
)


Expand Down
8 changes: 8 additions & 0 deletions bridge/bindings/qjs/array_methods.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// @ts-ignore
@Mixin()
export interface ArrayLikeMethodsMixin {
forEach(fn: Function, this_val?: any): void;
entries(): SyncIterator;
values(): SyncIterator;
keys(): SyncIterator;
}
5 changes: 5 additions & 0 deletions bridge/bindings/qjs/binding_initializer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "qjs_animation_event.h"
#include "qjs_blob.h"
#include "qjs_form_data.h"
#include "qjs_bounding_client_rect.h"
#include "qjs_canvas_gradient.h"
#include "qjs_canvas_pattern.h"
Expand Down Expand Up @@ -98,6 +99,7 @@
#include "qjs_ui_event.h"
#include "qjs_widget_element.h"
#include "qjs_window.h"
#include "qjs_sync_iterator.h"
#include "qjs_window_or_worker_global_scope.h"

namespace webf {
Expand All @@ -106,6 +108,7 @@ void InstallBindings(ExecutingContext* context) {
// Must follow the inheritance order when install.
// Exp: Node extends EventTarget, EventTarget must be install first.
QJSWindowOrWorkerGlobalScope::Install(context);
QJSSyncIterator::Install(context);
QJSLocation::Install(context);
QJSModuleManager::Install(context);
QJSConsole::Install(context);
Expand Down Expand Up @@ -200,6 +203,8 @@ void InstallBindings(ExecutingContext* context) {
QJSSVGStyleElement::Install(context);
QJSSVGLineElement::Install(context);

QJSFormData::Install(context);

// Legacy bindings, not standard.
QJSElementAttributes::Install(context);
}
Expand Down
8 changes: 8 additions & 0 deletions bridge/bindings/qjs/converter_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#ifndef BRIDGE_BINDINGS_QJS_CONVERTER_IMPL_H_
#define BRIDGE_BINDINGS_QJS_CONVERTER_IMPL_H_

#include <memory>
#include <type_traits>
#include "atomic_string.h"
#include "bindings/qjs/union_base.h"
Expand Down Expand Up @@ -384,6 +385,7 @@ struct Converter<IDLCallback> : public ConverterBase<IDLCallback> {
}
};


template <>
struct Converter<BlobPart> : public ConverterBase<BlobPart> {
using ImplType = BlobPart::ImplType;
Expand All @@ -398,6 +400,12 @@ struct Converter<BlobPart> : public ConverterBase<BlobPart> {

return data->ToQuickJS(ctx);
}
static JSValue ToValue(JSContext* ctx, std::shared_ptr<BlobPart> data) {
if (data == nullptr)
return JS_NULL;

return data->ToQuickJS(ctx);
}
};

template <>
Expand Down
2 changes: 1 addition & 1 deletion bridge/bindings/qjs/exception_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

namespace webf {

enum ErrorType { TypeError, InternalError, RangeError, ReferenceError, SyntaxError };
enum ErrorType { TypeError, InternalError, RangeError, ReferenceError, SyntaxError,ArgumentError };

// ExceptionState is a scope-like class and provides a way to store an exception.
class ExceptionState {
Expand Down
1 change: 1 addition & 0 deletions bridge/bindings/qjs/generated_code_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "atomic_string.h"
#include "bindings/qjs/dictionary_base.h"
#include "bindings/qjs/qjs_interface_bridge.h"
#include "core/html/forms/form_data.h"
#include "script_value.h"

#endif
28 changes: 28 additions & 0 deletions bridge/bindings/qjs/iterable.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (C) 2019-2022 The Kraken authors. All rights reserved.
* Copyright (C) 2022-present The WebF authors. All rights reserved.
*/

#include "iterable.h"

namespace webf {


ScriptValue ESCreateIterResultObject(JSContext* ctx, bool done, const ScriptValue& value) {
JSValue object = JS_NewObject(ctx);
JS_SetPropertyStr(ctx, object, "done", JS_NewBool(ctx, done));
JS_SetPropertyStr(ctx, object, "value", JS_DupValue(ctx, value.QJSValue()));
return ScriptValue(ctx, object);
}

ScriptValue ESCreateIterResultObject(JSContext* ctx, bool done, const ScriptValue& value1, const ScriptValue& value2) {
JSValue object = JS_NewObject(ctx);
JS_SetPropertyStr(ctx, object, "done", JS_NewBool(ctx, done));
JSValue array = JS_NewArray(ctx);
JS_SetPropertyInt64(ctx, array, 0, JS_DupValue(ctx, value1.QJSValue()));
JS_SetPropertyInt64(ctx, array, 1, JS_DupValue(ctx, value2.QJSValue()));
JS_SetPropertyStr(ctx, object, "value", array);
return ScriptValue(ctx, object);
}

}
62 changes: 62 additions & 0 deletions bridge/bindings/qjs/iterable.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright (C) 2022-present The WebF authors. All rights reserved.
*/

#ifndef WEBF_BINDINGS_QJS_ITERABLE_H_
#define WEBF_BINDINGS_QJS_ITERABLE_H_

#include "bindings/qjs/sync_iterator.h"

namespace webf {

ScriptValue ESCreateIterResultObject(JSContext* ctx, bool done, const ScriptValue& value);
ScriptValue ESCreateIterResultObject(JSContext* ctx, bool done, const ScriptValue& value1, const ScriptValue& value2);

class PairSyncIterationSource {
public:
virtual ScriptValue Next(SyncIterator::Kind, ExceptionState& exception_state) = 0;

virtual ScriptValue Value() = 0;
virtual bool Done() = 0;

virtual void Trace(GCVisitor* visitor) = 0;
virtual JSContext* ctx() = 0;

private:
};

class PairSyncIterable {
public:
SyncIterator* keys(ExceptionState& exception_state) {
std::shared_ptr<PairSyncIterationSource> source = CreateIterationSource(exception_state);
if (!source)
return nullptr;
return MakeGarbageCollected<SyncIterator>(source->ctx(), source, SyncIterator::Kind::kKey);
}

SyncIterator* values(ExceptionState& exception_state) {
std::shared_ptr<PairSyncIterationSource> source = CreateIterationSource(exception_state);
if (!source)
return nullptr;
return MakeGarbageCollected<SyncIterator>(source->ctx(), source, SyncIterator::Kind::kValue);
}

SyncIterator* entries(ExceptionState& exception_state) {
std::shared_ptr<PairSyncIterationSource> source = CreateIterationSource(exception_state);
if (!source)
return nullptr;
return MakeGarbageCollected<SyncIterator>(source->ctx(), source, SyncIterator::Kind::kKeyValue);
}

virtual void forEach(const std::shared_ptr<QJSFunction>& callback, ExceptionState& exception_state) = 0;
virtual void forEach(const std::shared_ptr<QJSFunction>& callback,
const ScriptValue& this_arg,
ExceptionState& exception_state) = 0;

private:
virtual std::shared_ptr<PairSyncIterationSource> CreateIterationSource(ExceptionState& exception_state) = 0;
};

} // namespace webf

#endif // WEBF_BINDINGS_QJS_ITERABLE_H_
14 changes: 11 additions & 3 deletions bridge/bindings/qjs/member_installer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "member_installer.h"
#include <quickjs/quickjs.h>
#include <string>
#include "core/executing_context.h"
#include "qjs_engine_patch.h"

Expand Down Expand Up @@ -67,14 +68,21 @@ void MemberInstaller::InstallAttributes(ExecutingContext* context,
}
}
}

// Defined a placeholder name in FormData to avoid using C++ keyword **delete**.
const char* fn_form_data_delete="form_data_delete";
void MemberInstaller::InstallFunctions(ExecutingContext* context,
JSValue root,
std::initializer_list<FunctionConfig> config) {
JSContext* ctx = context->ctx();
for (auto& c : config) {
JSValue function = JS_NewCFunction(ctx, c.function, c.name, c.length);
JS_DefinePropertyValueStr(ctx, root, c.name, function, c.flag);
std::string name = c.name;

// replace the placeholder name to real one.
if(c.name==fn_form_data_delete){
name = "delete";
}
JSValue function = JS_NewCFunction(ctx, c.function, name.c_str(), c.length);
JS_DefinePropertyValueStr(ctx, root, name.c_str(), function, c.flag);
}
}

Expand Down
34 changes: 34 additions & 0 deletions bridge/bindings/qjs/sync_iterator.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (C) 2022-present The WebF authors. All rights reserved.
*/

#include "bindings/qjs/sync_iterator.h"
#include "bindings/qjs/iterable.h"

namespace webf {

ScriptValue SyncIterator::value() {
return iteration_source_->Value();
}

ScriptValue SyncIterator::Symbol_iterator() {
auto iterator_return_func = [](JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) {
return JS_DupValue(ctx, this_val);
};
return ScriptValue(ctx(), JS_NewCFunction(ctx(), iterator_return_func, "iterator", 0));
}

bool SyncIterator::done() {
return iteration_source_->Done();
}

void SyncIterator::Trace(GCVisitor* visitor) const {
iteration_source_->Trace(visitor);
ScriptWrappable::Trace(visitor);
}

ScriptValue SyncIterator::next(ExceptionState& exception_state) {
return iteration_source_->Next(kind_, exception_state);
}

}
5 changes: 5 additions & 0 deletions bridge/bindings/qjs/sync_iterator.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
interface SyncIterator {
new(): void;
next(): any;
readonly [Symbol.iterator]: () => SyncIterator;
}
52 changes: 52 additions & 0 deletions bridge/bindings/qjs/sync_iterator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright (C) 2022-present The WebF authors. All rights reserved.
*/

#ifndef WEBF_BINDING_SYNC_ITERATOR_BASE
#define WEBF_BINDING_SYNC_ITERATOR_BASE

#include "bindings/qjs/cppgc/gc_visitor.h"
#include "bindings/qjs/exception_state.h"
#include "bindings/qjs/script_wrappable.h"
#include "core/script_state.h"

namespace webf {

class PairSyncIterationSource;

// SyncIteratorBase is the common base class of all sync iterator classes.
// Most importantly this class provides a way of type dispatching (e.g.
// overload resolutions, SFINAE technique, etc.) so that it's possible to
// distinguish sync iterators from anything else. Also it provides common
// implementation of sync iterators.
class SyncIterator : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
using ImplType = SyncIterator*;
// https://webidl.spec.whatwg.org/#default-iterator-object-kind
enum class Kind {
kKey,
kValue,
kKeyValue,
};

~SyncIterator() override = default;

ScriptValue next(ExceptionState& exception_state);
bool done();
ScriptValue value();
ScriptValue Symbol_iterator();

void Trace(GCVisitor* visitor) const override;

explicit SyncIterator(JSContext* ctx, std::shared_ptr<PairSyncIterationSource> iteration_source, Kind kind)
: iteration_source_(std::move(iteration_source)), kind_(kind), ScriptWrappable(ctx) {}

private:
const std::shared_ptr<PairSyncIterationSource> iteration_source_;
const Kind kind_;
};

} // namespace webf

#endif
6 changes: 6 additions & 0 deletions bridge/bindings/qjs/wrapper_type_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class TouchList;
// Define all built-in wrapper class id.
enum {
JS_CLASS_GC_TRACKER = JS_CLASS_INIT_COUNT + 1,
JS_CLASS_SYNC_ITERATOR,
JS_CLASS_BLOB,
JS_CLASS_EVENT,
JS_CLASS_ERROR_EVENT,
Expand Down Expand Up @@ -115,7 +116,12 @@ enum {
JS_CLASS_SVG_LENGTH,
JS_CLASS_SVG_ANIMATED_LENGTH,

//
JS_CLASS_FORM_DATA,

JS_CLASS_CUSTOM_CLASS_INIT_COUNT /* last entry for predefined classes */


};

// Callback when get property using index.
Expand Down
Loading
Loading