1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 18:27:35 +00:00

LibWeb+Meta: Add wrapper for the BufferSource/ArrayBufferView IDL types

These wrappers will make it much easier to do various operations on the
different ArrayBuffer-related classes in LibWeb compared to the current
solution, which is to just accept a Handle<Object> everywhere (and use
"any" in the *.idl files).

Co-Authored-By: Matthew Olsson <mattco@serenityos.org>
This commit is contained in:
Shannon Booth 2023-11-23 20:07:25 +13:00 committed by Andreas Kling
parent 54d0aafff0
commit 04c094343f
27 changed files with 286 additions and 71 deletions

View file

@ -180,7 +180,10 @@ CppType idl_type_name_to_cpp_type(Type const& type, Interface const& interface)
return { .name = "JS::Handle<JS::Object>", .sequence_storage_type = SequenceStorageType::Vector };
if (type.name() == "BufferSource")
return { .name = "JS::Handle<JS::Object>", .sequence_storage_type = SequenceStorageType::MarkedVector };
return { .name = "JS::Handle<WebIDL::BufferSource>", .sequence_storage_type = SequenceStorageType::MarkedVector };
if (type.name() == "ArrayBufferView")
return { .name = "JS::Handle<WebIDL::ArrayBufferView>", .sequence_storage_type = SequenceStorageType::MarkedVector };
if (type.name() == "File")
return { .name = "JS::Handle<FileAPI::File>", .sequence_storage_type = SequenceStorageType::MarkedVector };
@ -611,20 +614,33 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
} else if (parameter.type->name() == "BufferSource" || parameter.type->name() == "Float32Array" || parameter.type->name() == "Float64Array" || parameter.type->name() == "Uint8Array") {
if (optional) {
scoped_generator.append(R"~~~(
Optional<JS::Handle<JS::Object>> @cpp_name@;
Optional<JS::Handle<WebIDL::BufferSource>> @cpp_name@;
if (!@js_name@@js_suffix@.is_undefined()) {
)~~~");
} else {
scoped_generator.append(R"~~~(
JS::Handle<JS::Object> @cpp_name@;
JS::Handle<WebIDL::BufferSource> @cpp_name@;
)~~~");
}
scoped_generator.append(R"~~~(
if (!@js_name@@js_suffix@.is_object() || !(is<JS::TypedArrayBase>(@js_name@@js_suffix@.as_object()) || is<JS::ArrayBuffer>(@js_name@@js_suffix@.as_object()) || is<JS::DataView>(@js_name@@js_suffix@.as_object())))
return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "@parameter.type.name@");
// TODO: Should we make this a Variant?
@cpp_name@ = JS::make_handle(&@js_name@@js_suffix@.as_object());
@cpp_name@ = JS::make_handle(vm.heap().allocate<WebIDL::BufferSource>(realm, @js_name@@js_suffix@.as_object()));
)~~~");
if (optional) {
scoped_generator.append(R"~~~(
}
)~~~");
}
} else if (parameter.type->name() == "ArrayBufferView") {
scoped_generator.append(R"~~~(
if (!@js_name@@js_suffix@.is_object() || !(is<JS::TypedArrayBase>(@js_name@@js_suffix@.as_object()) || is<JS::DataView>(@js_name@@js_suffix@.as_object())))
return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "@parameter.type.name@");
auto @cpp_name@ = JS::make_handle(vm.heap().allocate<WebIDL::ArrayBufferView>(realm, @js_name@@js_suffix@.as_object()));
)~~~");
if (optional) {
scoped_generator.append(R"~~~(
@ -1124,28 +1140,40 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter
// 6. If Type(V) is Object and V has an [[ArrayBufferData]] internal slot, then
// 1. If types includes ArrayBuffer, then return the result of converting V to ArrayBuffer.
for (auto& type : types) {
if (type->name() == "BufferSource") {
union_generator.append(R"~~~(
if (is<JS::TypedArrayBase>(@js_name@@js_suffix@_object) || is<JS::ArrayBuffer>(@js_name@@js_suffix@_object) || is<JS::DataView>(@js_name@@js_suffix@_object))
return JS::make_handle(@js_name@@js_suffix@_object);
)~~~");
}
}
// 2. If types includes object, then return the IDL value that is a reference to the object V.
if (includes_object) {
if (any_of(types, [](auto const& type) { return type->name() == "ArrayBuffer"; }) || includes_object) {
union_generator.append(R"~~~(
return @js_name@@js_suffix@_object;
if (is<JS::ArrayBuffer>(@js_name@@js_suffix@_object))
return JS::make_handle(@js_name@@js_suffix@_object);
}
)~~~");
}
// FIXME: 7. If Type(V) is Object and V has a [[DataView]] internal slot, then:
// 1. If types includes DataView, then return the result of converting V to DataView.
// 2. If types includes object, then return the IDL value that is a reference to the object V.
// 7. If Type(V) is Object and V has a [[DataView]] internal slot, then:
// 1. If types includes DataView, then return the result of converting V to DataView.
// 2. If types includes object, then return the IDL value that is a reference to the object V.
if (any_of(types, [](auto const& type) { return type->name() == "DataView"; }) || includes_object) {
union_generator.append(R"~~~(
if (is<JS::DataView>(@js_name@@js_suffix@_object))
return JS::make_handle(@js_name@@js_suffix@_object);
}
)~~~");
}
// FIXME: 8. If Type(V) is Object and V has a [[TypedArrayName]] internal slot, then:
// 1. If types includes a typed array type whose name is the value of Vs [[TypedArrayName]] internal slot, then return the result of converting V to that type.
// 2. If types includes object, then return the IDL value that is a reference to the object V.
// 8. If Type(V) is Object and V has a [[TypedArrayName]] internal slot, then:
// 1. If types includes a typed array type whose name is the value of Vs [[TypedArrayName]] internal slot, then return the result of converting V to that type.
// 2. If types includes object, then return the IDL value that is a reference to the object V.
auto has_typed_array_name = any_of(types, [](auto const& type) {
return type->name().is_one_of("Int8Array"sv, "Int16Array"sv, "Int32Array"sv, "Uint8Array"sv, "Uint16Array"sv, "Uint32Array"sv, "Uint8ClampedArray"sv, "BigInt64Array"sv, "BigUint64Array", "Float32Array"sv, "Float64Array"sv);
});
if (has_typed_array_name || includes_object) {
union_generator.append(R"~~~(
if (is<JS::TypedArrayBase>(@js_name@@js_suffix@_object))
return JS::make_handle(@js_name@@js_suffix@_object);
}
)~~~");
}
// 9. If IsCallable(V) is true, then:
// 1. If types includes a callback function type, then return the result of converting V to that callback function type.
@ -1679,6 +1707,10 @@ static void generate_wrap_statement(SourceGenerator& generator, DeprecatedString
} else if (type.name() == "Location" || type.name() == "Promise" || type.name() == "Uint8Array" || type.name() == "Uint8ClampedArray" || type.name() == "any") {
scoped_generator.append(R"~~~(
@result_expression@ @value@;
)~~~");
} else if (type.name() == "ArrayBufferView" || type.name() == "BufferSource") {
scoped_generator.append(R"~~~(
@result_expression@ JS::Value(const_cast<JS::Object*>(@value@->raw_object().ptr()));
)~~~");
} else if (is<IDL::UnionType>(type)) {
auto& union_type = verify_cast<IDL::UnionType>(type);
@ -3359,6 +3391,7 @@ void generate_namespace_implementation(IDL::Interface const& interface, StringBu
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/HTML/Window.h>
#include <LibWeb/HTML/WindowProxy.h>
#include <LibWeb/WebIDL/Buffers.h>
#include <LibWeb/WebIDL/OverloadResolution.h>
)~~~");
@ -3570,6 +3603,7 @@ void generate_constructor_implementation(IDL::Interface const& interface, String
# include <LibWeb/URL/@name@.h>
#endif
#include <LibWeb/HTML/WindowProxy.h>
#include <LibWeb/WebIDL/Buffers.h>
#include <LibWeb/WebIDL/CallbackType.h>
)~~~");
@ -4023,6 +4057,7 @@ void generate_prototype_implementation(IDL::Interface const& interface, StringBu
#include <LibWeb/HTML/Scripting/Environments.h>
#include <LibWeb/HTML/Window.h>
#include <LibWeb/HTML/WindowProxy.h>
#include <LibWeb/WebIDL/Buffers.h>
#include <LibWeb/WebIDL/OverloadResolution.h>
#if __has_include(<LibWeb/Bindings/@prototype_base_class@.h>)