mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 05:07:35 +00:00
LibWeb: Support generating IDL namespaces
These are similar to prototypes and constructors in that they will now be lazily instantiated when they are first requested.
This commit is contained in:
parent
61ecdbca54
commit
020c2b59c4
5 changed files with 269 additions and 24 deletions
|
@ -2653,6 +2653,151 @@ JS_DEFINE_NATIVE_FUNCTION(@class_name@::values)
|
|||
}
|
||||
}
|
||||
|
||||
void generate_namespace_header(IDL::Interface const& interface, StringBuilder& builder)
|
||||
{
|
||||
SourceGenerator generator { builder };
|
||||
|
||||
generator.set("namespace_class", interface.namespace_class);
|
||||
|
||||
generator.append(R"~~~(
|
||||
#pragma once
|
||||
|
||||
#include <LibJS/Runtime/Object.h>
|
||||
|
||||
namespace Web::Bindings {
|
||||
|
||||
class @namespace_class@ final : public JS::Object {
|
||||
JS_OBJECT(@namespace_class@, JS::Object);
|
||||
|
||||
public:
|
||||
explicit @namespace_class@(JS::Realm&);
|
||||
virtual JS::ThrowCompletionOr<void> initialize(JS::Realm&) override;
|
||||
virtual ~@namespace_class@() override;
|
||||
|
||||
private:
|
||||
)~~~");
|
||||
|
||||
for (auto const& overload_set : interface.overload_sets) {
|
||||
auto function_generator = generator.fork();
|
||||
function_generator.set("function.name:snakecase", make_input_acceptable_cpp(overload_set.key.to_snakecase()));
|
||||
function_generator.append(R"~~~(
|
||||
JS_DECLARE_NATIVE_FUNCTION(@function.name:snakecase@);
|
||||
)~~~");
|
||||
if (overload_set.value.size() > 1) {
|
||||
for (auto i = 0u; i < overload_set.value.size(); ++i) {
|
||||
function_generator.set("overload_suffix", DeprecatedString::number(i));
|
||||
function_generator.append(R"~~~(
|
||||
JS_DECLARE_NATIVE_FUNCTION(@function.name:snakecase@@overload_suffix@);
|
||||
)~~~");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
generator.append(R"~~~(
|
||||
};
|
||||
|
||||
} // namespace Web::Bindings
|
||||
)~~~");
|
||||
}
|
||||
|
||||
void generate_namespace_implementation(IDL::Interface const& interface, StringBuilder& builder)
|
||||
{
|
||||
SourceGenerator generator { builder };
|
||||
|
||||
generator.set("name", interface.name);
|
||||
generator.set("namespace_class", interface.namespace_class);
|
||||
|
||||
generator.append(R"~~~(
|
||||
#include <AK/Function.h>
|
||||
#include <LibIDL/Types.h>
|
||||
#include <LibJS/Runtime/Error.h>
|
||||
#include <LibJS/Runtime/PrimitiveString.h>
|
||||
#include <LibJS/Runtime/Value.h>
|
||||
#include <LibWeb/Bindings/@namespace_class@.h>
|
||||
#include <LibWeb/Bindings/ExceptionOrUtils.h>
|
||||
#include <LibWeb/Bindings/Intrinsics.h>
|
||||
#include <LibWeb/HTML/Window.h>
|
||||
#include <LibWeb/HTML/WindowProxy.h>
|
||||
#include <LibWeb/WebIDL/OverloadResolution.h>
|
||||
|
||||
)~~~");
|
||||
|
||||
for (auto& path : interface.required_imported_paths)
|
||||
generate_include_for(generator, path);
|
||||
|
||||
emit_includes_for_all_imports(interface, generator, interface.pair_iterator_types.has_value());
|
||||
|
||||
generator.append(R"~~~(
|
||||
// FIXME: This is a total hack until we can figure out the namespace for a given type somehow.
|
||||
using namespace Web::CSS;
|
||||
using namespace Web::DOM;
|
||||
using namespace Web::DOMParsing;
|
||||
using namespace Web::Fetch;
|
||||
using namespace Web::FileAPI;
|
||||
using namespace Web::Geometry;
|
||||
using namespace Web::HighResolutionTime;
|
||||
using namespace Web::HTML;
|
||||
using namespace Web::IntersectionObserver;
|
||||
using namespace Web::RequestIdleCallback;
|
||||
using namespace Web::ResizeObserver;
|
||||
using namespace Web::Selection;
|
||||
using namespace Web::Streams;
|
||||
using namespace Web::UIEvents;
|
||||
using namespace Web::URL;
|
||||
using namespace Web::XHR;
|
||||
using namespace Web::WebGL;
|
||||
using namespace Web::WebIDL;
|
||||
|
||||
namespace Web::Bindings {
|
||||
|
||||
@namespace_class@::@namespace_class@(JS::Realm& realm)
|
||||
: Object(ConstructWithoutPrototypeTag::Tag, realm)
|
||||
{
|
||||
}
|
||||
|
||||
@namespace_class@::~@namespace_class@()
|
||||
{
|
||||
}
|
||||
|
||||
JS::ThrowCompletionOr<void> @namespace_class@::initialize(JS::Realm& realm)
|
||||
{
|
||||
[[maybe_unused]] auto& vm = this->vm();
|
||||
[[maybe_unused]] u8 default_attributes = JS::Attribute::Enumerable;
|
||||
|
||||
MUST_OR_THROW_OOM(Base::initialize(realm));
|
||||
|
||||
)~~~");
|
||||
|
||||
// https://webidl.spec.whatwg.org/#es-operations
|
||||
for (auto const& overload_set : interface.overload_sets) {
|
||||
auto function_generator = generator.fork();
|
||||
function_generator.set("function.name", overload_set.key);
|
||||
function_generator.set("function.name:snakecase", make_input_acceptable_cpp(overload_set.key.to_snakecase()));
|
||||
function_generator.set("function.length", DeprecatedString::number(get_shortest_function_length(overload_set.value)));
|
||||
|
||||
function_generator.append(R"~~~(
|
||||
define_native_function(realm, "@function.name@", @function.name:snakecase@, @function.length@, default_attributes);
|
||||
)~~~");
|
||||
}
|
||||
|
||||
generator.append(R"~~~(
|
||||
return {};
|
||||
}
|
||||
)~~~");
|
||||
|
||||
for (auto const& function : interface.functions)
|
||||
generate_function(generator, function, StaticFunction::Yes, interface.namespace_class, interface.name, interface);
|
||||
for (auto const& overload_set : interface.overload_sets) {
|
||||
if (overload_set.value.size() == 1)
|
||||
continue;
|
||||
generate_overload_arbiter(generator, overload_set, interface.namespace_class);
|
||||
}
|
||||
|
||||
generator.append(R"~~~(
|
||||
} // namespace Web::Bindings
|
||||
)~~~");
|
||||
}
|
||||
|
||||
void generate_constructor_header(IDL::Interface const& interface, StringBuilder& builder)
|
||||
{
|
||||
SourceGenerator generator { builder };
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
extern Vector<StringView> s_header_search_paths;
|
||||
|
||||
namespace IDL {
|
||||
void generate_namespace_header(IDL::Interface const&, StringBuilder&);
|
||||
void generate_namespace_implementation(IDL::Interface const&, StringBuilder&);
|
||||
void generate_constructor_header(IDL::Interface const&, StringBuilder&);
|
||||
void generate_constructor_implementation(IDL::Interface const&, StringBuilder&);
|
||||
void generate_prototype_header(IDL::Interface const&, StringBuilder&);
|
||||
|
@ -36,6 +38,8 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
StringView output_path = "-"sv;
|
||||
StringView depfile_path;
|
||||
StringView depfile_target;
|
||||
bool namespace_header_mode = false;
|
||||
bool namespace_implementation_mode = false;
|
||||
bool constructor_header_mode = false;
|
||||
bool constructor_implementation_mode = false;
|
||||
bool prototype_header_mode = false;
|
||||
|
@ -44,6 +48,8 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
bool iterator_prototype_implementation_mode = false;
|
||||
bool global_mixin_header_mode = false;
|
||||
bool global_mixin_implementation_mode = false;
|
||||
args_parser.add_option(namespace_header_mode, "Generate the namespace .h file", "namespace-header", 'N');
|
||||
args_parser.add_option(namespace_implementation_mode, "Generate the namespace .cpp file", "namespace-implementation", 'A');
|
||||
args_parser.add_option(constructor_header_mode, "Generate the constructor .h file", "constructor-header", 'C');
|
||||
args_parser.add_option(constructor_implementation_mode, "Generate the constructor .cpp file", "constructor-implementation", 'O');
|
||||
args_parser.add_option(prototype_header_mode, "Generate the prototype .h file", "prototype-header", 'P');
|
||||
|
@ -136,6 +142,13 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
}
|
||||
|
||||
StringBuilder output_builder;
|
||||
|
||||
if (namespace_header_mode)
|
||||
IDL::generate_namespace_header(interface, output_builder);
|
||||
|
||||
if (namespace_implementation_mode)
|
||||
IDL::generate_namespace_implementation(interface, output_builder);
|
||||
|
||||
if (constructor_header_mode)
|
||||
IDL::generate_constructor_header(interface, output_builder);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue