mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 09:38:11 +00:00
AK: Eradicate the uses of out().
This commit is contained in:
parent
61e73b1a7b
commit
88bca152c9
7 changed files with 475 additions and 259 deletions
|
@ -137,7 +137,7 @@ void IRCAppWindow::setup_actions()
|
||||||
});
|
});
|
||||||
|
|
||||||
m_close_query_action = GUI::Action::create("Close query", { Mod_Ctrl, Key_D }, Gfx::Bitmap::load_from_file("/res/icons/16x16/irc-close-query.png"), [](auto&) {
|
m_close_query_action = GUI::Action::create("Close query", { Mod_Ctrl, Key_D }, Gfx::Bitmap::load_from_file("/res/icons/16x16/irc-close-query.png"), [](auto&) {
|
||||||
out() << "FIXME: Implement close-query action";
|
outln("FIXME: Implement close-query action");
|
||||||
});
|
});
|
||||||
|
|
||||||
m_change_nick_action = GUI::Action::create("Change nickname", Gfx::Bitmap::load_from_file("/res/icons/16x16/irc-nick.png"), [this](auto&) {
|
m_change_nick_action = GUI::Action::create("Change nickname", Gfx::Bitmap::load_from_file("/res/icons/16x16/irc-nick.png"), [this](auto&) {
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <AK/JsonObject.h>
|
#include <AK/JsonObject.h>
|
||||||
|
#include <AK/SourceGenerator.h>
|
||||||
#include <AK/StringBuilder.h>
|
#include <AK/StringBuilder.h>
|
||||||
#include <LibCore/File.h>
|
#include <LibCore/File.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
@ -48,7 +49,7 @@ static String title_casify(const String& dashy_name)
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
fprintf(stderr, "usage: %s <path/to/CSS/Properties.json>\n", argv[0]);
|
warnln("usage: {} <path/to/CSS/Properties.json>", argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
auto file = Core::File::construct(argv[1]);
|
auto file = Core::File::construct(argv[1]);
|
||||||
|
@ -59,34 +60,59 @@ int main(int argc, char** argv)
|
||||||
ASSERT(json.has_value());
|
ASSERT(json.has_value());
|
||||||
ASSERT(json.value().is_object());
|
ASSERT(json.value().is_object());
|
||||||
|
|
||||||
out() << "#include <AK/Assertions.h>";
|
StringBuilder builder;
|
||||||
out() << "#include <LibWeb/CSS/PropertyID.h>";
|
SourceGenerator generator { builder };
|
||||||
out() << "namespace Web::CSS {";
|
|
||||||
|
|
||||||
out() << "PropertyID property_id_from_string(const StringView& string) {";
|
generator.append(R"~~~(
|
||||||
|
#include <AK/Assertions.h>
|
||||||
|
#include <LibWeb/CSS/PropertyID.h>
|
||||||
|
|
||||||
|
namespace Web::CSS {
|
||||||
|
|
||||||
|
PropertyID property_id_from_string(const StringView& string)
|
||||||
|
{
|
||||||
|
)~~~");
|
||||||
|
|
||||||
json.value().as_object().for_each_member([&](auto& name, auto& value) {
|
json.value().as_object().for_each_member([&](auto& name, auto& value) {
|
||||||
ASSERT(value.is_object());
|
ASSERT(value.is_object());
|
||||||
out() << " if (string.equals_ignoring_case(\"" << name << "\"))";
|
|
||||||
out() << " return PropertyID::" << title_casify(name) << ";";
|
auto member_generator = generator.fork();
|
||||||
|
member_generator.set("name", name);
|
||||||
|
member_generator.set("name:titlecase", title_casify(name));
|
||||||
|
member_generator.append(R"~~~(
|
||||||
|
if (string.equals_ignoring_case("@name@"))
|
||||||
|
return PropertyID::@name:titlecase@;
|
||||||
|
)~~~");
|
||||||
});
|
});
|
||||||
|
|
||||||
out() << " return PropertyID::Invalid;";
|
generator.append(R"~~~(
|
||||||
|
return PropertyID::Invalid;
|
||||||
out() << "}";
|
}
|
||||||
|
|
||||||
out() << "const char* string_from_property_id(PropertyID property_id) {";
|
const char* string_from_property_id(PropertyID property_id) {
|
||||||
out() << " switch (property_id) {";
|
switch (property_id) {
|
||||||
json.value().as_object().for_each_member([&](auto& name, auto& value) {
|
)~~~");
|
||||||
ASSERT(value.is_object());
|
|
||||||
out() << " case PropertyID::" << title_casify(name) << ":";
|
json.value().as_object().for_each_member([&](auto& name, auto& value) {
|
||||||
out() << " return \"" << name << "\";";
|
ASSERT(value.is_object());
|
||||||
});
|
|
||||||
out() << " default:";
|
auto member_generator = generator.fork();
|
||||||
out() << " return \"(invalid CSS::PropertyID)\";";
|
member_generator.set("name", name);
|
||||||
out() << " }";
|
member_generator.set("name:titlecase", title_casify(name));
|
||||||
out() << "}";
|
member_generator.append(R"~~~(
|
||||||
out() << "}";
|
case PropertyID::@name:titlecase@:
|
||||||
|
return "@name@";
|
||||||
return 0;
|
)~~~");
|
||||||
|
});
|
||||||
|
|
||||||
|
generator.append(R"~~~(
|
||||||
|
default:
|
||||||
|
return "(invalid CSS::PropertyID)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Web::CSS
|
||||||
|
)~~~");
|
||||||
|
|
||||||
|
outln("{}", generator.as_string_view());
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <AK/JsonObject.h>
|
#include <AK/JsonObject.h>
|
||||||
|
#include <AK/SourceGenerator.h>
|
||||||
#include <AK/StringBuilder.h>
|
#include <AK/StringBuilder.h>
|
||||||
#include <LibCore/File.h>
|
#include <LibCore/File.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
@ -48,7 +49,7 @@ static String title_casify(const String& dashy_name)
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
fprintf(stderr, "usage: %s <path/to/CSS/Properties.json>\n", argv[0]);
|
warnln("usage: {} <path/to/CSS/Properties.json>", argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
auto file = Core::File::construct(argv[1]);
|
auto file = Core::File::construct(argv[1]);
|
||||||
|
@ -59,30 +60,46 @@ int main(int argc, char** argv)
|
||||||
ASSERT(json.has_value());
|
ASSERT(json.has_value());
|
||||||
ASSERT(json.value().is_object());
|
ASSERT(json.value().is_object());
|
||||||
|
|
||||||
out() << "#pragma once";
|
StringBuilder builder;
|
||||||
out() << "#include <AK/StringView.h>";
|
SourceGenerator generator { builder };
|
||||||
out() << "#include <AK/Traits.h>";
|
generator.append(R"~~~(
|
||||||
|
#pragma once
|
||||||
|
|
||||||
out() << "namespace Web::CSS {";
|
#include <AK/StringView.h>
|
||||||
out() << "enum class PropertyID {";
|
#include <AK/Traits.h>
|
||||||
out() << " Invalid,";
|
|
||||||
|
namespace Web::CSS {
|
||||||
|
|
||||||
|
enum class PropertyID {
|
||||||
|
Invalid,
|
||||||
|
)~~~");
|
||||||
|
|
||||||
json.value().as_object().for_each_member([&](auto& name, auto& value) {
|
json.value().as_object().for_each_member([&](auto& name, auto& value) {
|
||||||
ASSERT(value.is_object());
|
ASSERT(value.is_object());
|
||||||
out() << " " << title_casify(name) << ",";
|
|
||||||
|
auto member_generator = generator.fork();
|
||||||
|
member_generator.set("name:titlecase", title_casify(name));
|
||||||
|
|
||||||
|
member_generator.append(R"~~~(
|
||||||
|
@name:titlecase@,
|
||||||
|
)~~~");
|
||||||
});
|
});
|
||||||
|
|
||||||
out() << "};\n\
|
generator.append(R"~~~(
|
||||||
PropertyID property_id_from_string(const StringView&);\n\
|
};
|
||||||
const char* string_from_property_id(PropertyID);\n\
|
|
||||||
}\n\
|
|
||||||
\n\
|
|
||||||
namespace AK {\n\
|
|
||||||
template<>\n\
|
|
||||||
struct Traits<Web::CSS::PropertyID> : public GenericTraits<Web::CSS::PropertyID> {\n\
|
|
||||||
static unsigned hash(Web::CSS::PropertyID property_id) { return int_hash((unsigned)property_id); }\n\
|
|
||||||
};\n\
|
|
||||||
}\n";
|
|
||||||
|
|
||||||
return 0;
|
PropertyID property_id_from_string(const StringView&);
|
||||||
|
const char* string_from_property_id(PropertyID);
|
||||||
|
|
||||||
|
} // namespace Web::CSS
|
||||||
|
|
||||||
|
namespace AK {
|
||||||
|
template<>
|
||||||
|
struct Traits<Web::CSS::PropertyID> : public GenericTraits<Web::CSS::PropertyID> {
|
||||||
|
static unsigned hash(Web::CSS::PropertyID property_id) { return int_hash((unsigned)property_id); }
|
||||||
|
};
|
||||||
|
} // namespace AK
|
||||||
|
)~~~");
|
||||||
|
|
||||||
|
outln("{}", generator.as_string_view());
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include <AK/GenericLexer.h>
|
#include <AK/GenericLexer.h>
|
||||||
#include <AK/HashMap.h>
|
#include <AK/HashMap.h>
|
||||||
#include <AK/LexicalPath.h>
|
#include <AK/LexicalPath.h>
|
||||||
|
#include <AK/SourceGenerator.h>
|
||||||
#include <AK/StringBuilder.h>
|
#include <AK/StringBuilder.h>
|
||||||
#include <LibCore/ArgsParser.h>
|
#include <LibCore/ArgsParser.h>
|
||||||
#include <LibCore/File.h>
|
#include <LibCore/File.h>
|
||||||
|
@ -286,7 +287,7 @@ int main(int argc, char** argv)
|
||||||
auto interface = IDL::parse_interface(data);
|
auto interface = IDL::parse_interface(data);
|
||||||
|
|
||||||
if (!interface) {
|
if (!interface) {
|
||||||
fprintf(stderr, "Cannot parse %s\n", path);
|
warnln("Cannot parse {}", path);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,201 +367,301 @@ static bool is_wrappable_type(const IDL::Type& type)
|
||||||
|
|
||||||
static void generate_header(const IDL::Interface& interface)
|
static void generate_header(const IDL::Interface& interface)
|
||||||
{
|
{
|
||||||
auto& wrapper_class = interface.wrapper_class;
|
StringBuilder builder;
|
||||||
auto& wrapper_base_class = interface.wrapper_base_class;
|
SourceGenerator generator { builder };
|
||||||
|
|
||||||
out() << "#pragma once";
|
generator.set("name", interface.name);
|
||||||
out() << "#include <LibWeb/Bindings/Wrapper.h>";
|
generator.set("fully_qualified_name", interface.fully_qualified_name);
|
||||||
|
generator.set("wrapper_base_class", interface.wrapper_base_class);
|
||||||
|
generator.set("wrapper_class", interface.wrapper_class);
|
||||||
|
generator.set("wrapper_class:snakecase", snake_name(interface.wrapper_class));
|
||||||
|
|
||||||
// FIXME: This is very strange.
|
generator.append(R"~~~(
|
||||||
out() << "#if __has_include(<LibWeb/DOM/" << interface.name << ".h>)";
|
#pragma once
|
||||||
out() << "#include <LibWeb/DOM/" << interface.name << ".h>";
|
|
||||||
out() << "#elif __has_include(<LibWeb/HTML/" << interface.name << ".h>)";
|
|
||||||
out() << "#include <LibWeb/HTML/" << interface.name << ".h>";
|
|
||||||
out() << "#elif __has_include(<LibWeb/UIEvents/" << interface.name << ".h>)";
|
|
||||||
out() << "#include <LibWeb/UIEvents/" << interface.name << ".h>";
|
|
||||||
out() << "#elif __has_include(<LibWeb/HighResolutionTime/" << interface.name << ".h>)";
|
|
||||||
out() << "#include <LibWeb/HighResolutionTime/" << interface.name << ".h>";
|
|
||||||
out() << "#elif __has_include(<LibWeb/SVG/" << interface.name << ".h>)";
|
|
||||||
out() << "#include <LibWeb/SVG/" << interface.name << ".h>";
|
|
||||||
out() << "#endif";
|
|
||||||
|
|
||||||
if (wrapper_base_class != "Wrapper")
|
#include <LibWeb/Bindings/Wrapper.h>
|
||||||
out() << "#include <LibWeb/Bindings/" << wrapper_base_class << ".h>";
|
|
||||||
|
|
||||||
out() << "namespace Web::Bindings {";
|
// FIXME: This is very strange.
|
||||||
|
#if __has_include(<LibWeb/DOM/@name@.h>)
|
||||||
|
# include <LibWeb/DOM/@name@.h>
|
||||||
|
#elif __has_include(<LibWeb/HTML/@name@.h>)
|
||||||
|
# include <LibWeb/HTML/@name@.h>
|
||||||
|
#elif __has_include(<LibWeb/UIEvents/@name@.h>)
|
||||||
|
# include <LibWeb/UIEvents/@name@.h>
|
||||||
|
#elif __has_include(<LibWeb/HighResolutionTime/@name@.h>)
|
||||||
|
# include <LibWeb/HighResolutionTime/@name@.h>
|
||||||
|
#elif __has_include(<LibWeb/SVG/@name@.h>)
|
||||||
|
# include <LibWeb/SVG/@name@.h>
|
||||||
|
#endif
|
||||||
|
)~~~");
|
||||||
|
|
||||||
out() << "class " << wrapper_class << " : public " << wrapper_base_class << " {";
|
if (interface.wrapper_base_class != "Wrapper") {
|
||||||
out() << " JS_OBJECT(" << wrapper_class << ", " << wrapper_base_class << ");";
|
generator.append(R"~~~(
|
||||||
out() << "public:";
|
#include <LibWeb/Bindings/@wrapper_base_class@.h>
|
||||||
out() << " " << wrapper_class << "(JS::GlobalObject&, " << interface.fully_qualified_name << "&);";
|
)~~~");
|
||||||
out() << " virtual void initialize(JS::GlobalObject&) override;";
|
|
||||||
out() << " virtual ~" << wrapper_class << "() override;";
|
|
||||||
|
|
||||||
if (wrapper_base_class == "Wrapper") {
|
|
||||||
out() << " " << interface.fully_qualified_name << "& impl() { return *m_impl; }";
|
|
||||||
out() << " const " << interface.fully_qualified_name << "& impl() const { return *m_impl; }";
|
|
||||||
} else {
|
|
||||||
out() << " " << interface.fully_qualified_name << "& impl() { return static_cast<" << interface.fully_qualified_name << "&>(" << wrapper_base_class << "::impl()); }";
|
|
||||||
out() << " const " << interface.fully_qualified_name << "& impl() const { return static_cast<const " << interface.fully_qualified_name << "&>(" << wrapper_base_class << "::impl()); }";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto is_foo_wrapper_name = snake_name(String::format("Is%s", wrapper_class.characters()));
|
generator.append(R"~~~(
|
||||||
out() << " virtual bool " << is_foo_wrapper_name << "() const final { return true; }";
|
namespace Web::Bindings {
|
||||||
|
|
||||||
out() << "private:";
|
class @wrapper_class@ : public @wrapper_base_class@ {
|
||||||
|
JS_OBJECT(@wrapper_class@, @wrapper_base_class@);
|
||||||
|
public:
|
||||||
|
@wrapper_class@(JS::GlobalObject&, @fully_qualified_name@&);
|
||||||
|
virtual void initialize(JS::GlobalObject&) override;
|
||||||
|
virtual ~@wrapper_class@() override;
|
||||||
|
)~~~");
|
||||||
|
|
||||||
|
if (interface.wrapper_base_class == "Wrapper") {
|
||||||
|
generator.append(R"~~~(
|
||||||
|
@fully_qualified_name@& impl() { return *m_impl; }
|
||||||
|
const @fully_qualified_name@& impl() const { return *m_impl; }
|
||||||
|
)~~~");
|
||||||
|
} else {
|
||||||
|
generator.append(R"~~~(
|
||||||
|
@fully_qualified_name@& impl() { return static_cast<@fully_qualified_name@&>(@wrapper_base_class@::impl()); }
|
||||||
|
const @fully_qualified_name@& impl() const { return static_cast<const @fully_qualified_name@&>(@wrapper_base_class@::impl()); }
|
||||||
|
)~~~");
|
||||||
|
}
|
||||||
|
|
||||||
|
generator.append(R"~~~(
|
||||||
|
virtual bool is_@wrapper_class:snakecase@() const final { return true; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
)~~~");
|
||||||
|
|
||||||
for (auto& function : interface.functions) {
|
for (auto& function : interface.functions) {
|
||||||
out() << " JS_DECLARE_NATIVE_FUNCTION(" << snake_name(function.name) << ");";
|
auto function_generator = generator.fork();
|
||||||
|
function_generator.set("function.name:snakecase", snake_name(function.name));
|
||||||
|
function_generator.append(R"~~~(
|
||||||
|
JS_DECLARE_NATIVE_FUNCTION(@function.name:snakecase@);
|
||||||
|
)~~~");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& attribute : interface.attributes) {
|
for (auto& attribute : interface.attributes) {
|
||||||
out() << " JS_DECLARE_NATIVE_GETTER(" << snake_name(attribute.name) << "_getter);";
|
auto attribute_generator = generator.fork();
|
||||||
if (!attribute.readonly)
|
attribute_generator.set("attribute.name:snakecase", snake_name(attribute.name));
|
||||||
out() << " JS_DECLARE_NATIVE_SETTER(" << snake_name(attribute.name) << "_setter);";
|
attribute_generator.append(R"~~~(
|
||||||
|
JS_DECLARE_NATIVE_GETTER(@attribute.name:snakecase@_getter);
|
||||||
|
)~~~");
|
||||||
|
|
||||||
|
if (!attribute.readonly) {
|
||||||
|
attribute_generator.append(R"~~~(
|
||||||
|
JS_DECLARE_NATIVE_SETTER(@attribute.name:snakecase@_setter);
|
||||||
|
)~~~");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wrapper_base_class == "Wrapper") {
|
if (interface.wrapper_base_class == "Wrapper") {
|
||||||
out() << " NonnullRefPtr<" << interface.fully_qualified_name << "> m_impl;";
|
generator.append(R"~~~(
|
||||||
|
NonnullRefPtr<@fully_qualified_name@> m_impl;
|
||||||
|
)~~~");
|
||||||
}
|
}
|
||||||
|
|
||||||
out() << "};";
|
generator.append(R"~~~(
|
||||||
|
};
|
||||||
|
)~~~");
|
||||||
|
|
||||||
if (should_emit_wrapper_factory(interface)) {
|
if (should_emit_wrapper_factory(interface)) {
|
||||||
out() << wrapper_class << "* wrap(JS::GlobalObject&, " << interface.fully_qualified_name << "&);";
|
generator.append(R"~~~(
|
||||||
|
@wrapper_class@* wrap(JS::GlobalObject&, @fully_qualified_name@&);
|
||||||
|
)~~~");
|
||||||
}
|
}
|
||||||
|
|
||||||
out() << "}";
|
generator.append(R"~~~(
|
||||||
|
} // namespace Web::Bindings
|
||||||
|
)~~~");
|
||||||
|
|
||||||
|
outln("{}", generator.as_string_view());
|
||||||
}
|
}
|
||||||
|
|
||||||
void generate_implementation(const IDL::Interface& interface)
|
void generate_implementation(const IDL::Interface& interface)
|
||||||
{
|
{
|
||||||
auto& wrapper_class = interface.wrapper_class;
|
StringBuilder builder;
|
||||||
auto& wrapper_base_class = interface.wrapper_base_class;
|
SourceGenerator generator { builder };
|
||||||
|
|
||||||
out() << "#include <AK/FlyString.h>";
|
generator.set("wrapper_class", interface.wrapper_class);
|
||||||
out() << "#include <LibJS/Runtime/Array.h>";
|
generator.set("wrapper_base_class", interface.wrapper_base_class);
|
||||||
out() << "#include <LibJS/Runtime/Value.h>";
|
generator.set("fully_qualified_name", interface.fully_qualified_name);
|
||||||
out() << "#include <LibJS/Runtime/GlobalObject.h>";
|
|
||||||
out() << "#include <LibJS/Runtime/Error.h>";
|
|
||||||
out() << "#include <LibJS/Runtime/Function.h>";
|
|
||||||
out() << "#include <LibJS/Runtime/Uint8ClampedArray.h>";
|
|
||||||
out() << "#include <LibWeb/Bindings/NodeWrapperFactory.h>";
|
|
||||||
out() << "#include <LibWeb/Bindings/" << wrapper_class << ".h>";
|
|
||||||
out() << "#include <LibWeb/DOM/Element.h>";
|
|
||||||
out() << "#include <LibWeb/DOM/EventListener.h>";
|
|
||||||
out() << "#include <LibWeb/HTML/HTMLElement.h>";
|
|
||||||
out() << "#include <LibWeb/Origin.h>";
|
|
||||||
out() << "#include <LibWeb/Bindings/CommentWrapper.h>";
|
|
||||||
out() << "#include <LibWeb/Bindings/DocumentWrapper.h>";
|
|
||||||
out() << "#include <LibWeb/Bindings/DocumentFragmentWrapper.h>";
|
|
||||||
out() << "#include <LibWeb/Bindings/DocumentTypeWrapper.h>";
|
|
||||||
out() << "#include <LibWeb/Bindings/HTMLCanvasElementWrapper.h>";
|
|
||||||
out() << "#include <LibWeb/Bindings/HTMLHeadElementWrapper.h>";
|
|
||||||
out() << "#include <LibWeb/Bindings/HTMLImageElementWrapper.h>";
|
|
||||||
out() << "#include <LibWeb/Bindings/ImageDataWrapper.h>";
|
|
||||||
out() << "#include <LibWeb/Bindings/TextWrapper.h>";
|
|
||||||
out() << "#include <LibWeb/Bindings/CanvasRenderingContext2DWrapper.h>";
|
|
||||||
out() << "#include <LibWeb/Bindings/WindowObject.h>";
|
|
||||||
|
|
||||||
// FIXME: This is a total hack until we can figure out the namespace for a given type somehow.
|
generator.append(R"~~~(
|
||||||
out() << "using namespace Web::DOM;";
|
#include <AK/FlyString.h>
|
||||||
out() << "using namespace Web::HTML;";
|
#include <LibJS/Runtime/Array.h>
|
||||||
|
#include <LibJS/Runtime/Error.h>
|
||||||
|
#include <LibJS/Runtime/Function.h>
|
||||||
|
#include <LibJS/Runtime/GlobalObject.h>
|
||||||
|
#include <LibJS/Runtime/Uint8ClampedArray.h>
|
||||||
|
#include <LibJS/Runtime/Value.h>
|
||||||
|
#include <LibWeb/Bindings/@wrapper_class@.h>
|
||||||
|
#include <LibWeb/Bindings/CanvasRenderingContext2DWrapper.h>
|
||||||
|
#include <LibWeb/Bindings/CommentWrapper.h>
|
||||||
|
#include <LibWeb/Bindings/DocumentFragmentWrapper.h>
|
||||||
|
#include <LibWeb/Bindings/DocumentTypeWrapper.h>
|
||||||
|
#include <LibWeb/Bindings/DocumentWrapper.h>
|
||||||
|
#include <LibWeb/Bindings/HTMLCanvasElementWrapper.h>
|
||||||
|
#include <LibWeb/Bindings/HTMLHeadElementWrapper.h>
|
||||||
|
#include <LibWeb/Bindings/HTMLImageElementWrapper.h>
|
||||||
|
#include <LibWeb/Bindings/ImageDataWrapper.h>
|
||||||
|
#include <LibWeb/Bindings/NodeWrapperFactory.h>
|
||||||
|
#include <LibWeb/Bindings/TextWrapper.h>
|
||||||
|
#include <LibWeb/Bindings/WindowObject.h>
|
||||||
|
#include <LibWeb/DOM/Element.h>
|
||||||
|
#include <LibWeb/DOM/EventListener.h>
|
||||||
|
#include <LibWeb/HTML/HTMLElement.h>
|
||||||
|
#include <LibWeb/Origin.h>
|
||||||
|
|
||||||
out() << "namespace Web::Bindings {";
|
// FIXME: This is a total hack until we can figure out the namespace for a given type somehow.
|
||||||
|
using namespace Web::DOM;
|
||||||
|
using namespace Web::HTML;
|
||||||
|
|
||||||
// Implementation: Wrapper constructor
|
namespace Web::Bindings {
|
||||||
out() << wrapper_class << "::" << wrapper_class << "(JS::GlobalObject& global_object, " << interface.fully_qualified_name << "& impl)";
|
|
||||||
if (wrapper_base_class == "Wrapper") {
|
)~~~");
|
||||||
out() << " : Wrapper(*global_object.object_prototype())";
|
|
||||||
out() << " , m_impl(impl)";
|
if (interface.wrapper_base_class == "Wrapper") {
|
||||||
|
generator.append(R"~~~(
|
||||||
|
@wrapper_class@::@wrapper_class@(JS::GlobalObject& global_object, @fully_qualified_name@& impl)
|
||||||
|
: Wrapper(*global_object.object_prototype())
|
||||||
|
, m_impl(impl)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
)~~~");
|
||||||
} else {
|
} else {
|
||||||
out() << " : " << wrapper_base_class << "(global_object, impl)";
|
generator.append(R"~~~(
|
||||||
|
@wrapper_class@::@wrapper_class@(JS::GlobalObject& global_object, @fully_qualified_name@& impl)
|
||||||
|
: @wrapper_base_class@(global_object, impl)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
)~~~");
|
||||||
}
|
}
|
||||||
out() << "{";
|
|
||||||
out() << "}";
|
|
||||||
|
|
||||||
// Implementation: Wrapper initialize()
|
generator.append(R"~~~(
|
||||||
out() << "void " << wrapper_class << "::initialize(JS::GlobalObject& global_object)";
|
void @wrapper_class@::initialize(JS::GlobalObject& global_object)
|
||||||
out() << "{";
|
{
|
||||||
out() << " [[maybe_unused]] u8 default_attributes = JS::Attribute::Enumerable | JS::Attribute::Configurable;";
|
[[maybe_unused]] u8 default_attributes = JS::Attribute::Enumerable | JS::Attribute::Configurable;
|
||||||
out() << " " << wrapper_base_class << "::initialize(global_object);";
|
|
||||||
|
@wrapper_base_class@::initialize(global_object);
|
||||||
|
)~~~");
|
||||||
|
|
||||||
for (auto& attribute : interface.attributes) {
|
for (auto& attribute : interface.attributes) {
|
||||||
out() << " define_native_property(\"" << attribute.name << "\", " << attribute.getter_callback_name << ", " << (attribute.readonly ? "nullptr" : attribute.setter_callback_name) << ", default_attributes);";
|
auto attribute_generator = generator.fork();
|
||||||
|
attribute_generator.set("attribute.name", attribute.name);
|
||||||
|
attribute_generator.set("attribute.getter_callback", attribute.getter_callback_name);
|
||||||
|
|
||||||
|
if (attribute.readonly)
|
||||||
|
attribute_generator.set("attribute.setter_callback", "nullptr");
|
||||||
|
else
|
||||||
|
attribute_generator.set("attribute.setter_callback", attribute.setter_callback_name);
|
||||||
|
|
||||||
|
attribute_generator.append(R"~~~(
|
||||||
|
define_native_property("@attribute.name@", @attribute.getter_callback@, @attribute.setter_callback@, default_attributes);
|
||||||
|
)~~~");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& function : interface.functions) {
|
for (auto& function : interface.functions) {
|
||||||
out() << " define_native_function(\"" << function.name << "\", " << snake_name(function.name) << ", " << function.length() << ", default_attributes);";
|
auto function_generator = generator.fork();
|
||||||
|
function_generator.set("function.name", function.name);
|
||||||
|
function_generator.set("function.name:snakecase", snake_name(function.name));
|
||||||
|
function_generator.set("function.name:length", String::number(function.name.length()));
|
||||||
|
|
||||||
|
function_generator.append(R"~~~(
|
||||||
|
define_native_function("@function.name@", @function.name:snakecase@, @function.name:length@, default_attributes);
|
||||||
|
)~~~");
|
||||||
}
|
}
|
||||||
|
|
||||||
out() << "}";
|
generator.append(R"~~~(
|
||||||
|
}
|
||||||
|
|
||||||
// Implementation: Wrapper destructor
|
@wrapper_class@::~@wrapper_class@()
|
||||||
out() << wrapper_class << "::~" << wrapper_class << "()";
|
{
|
||||||
out() << "{";
|
}
|
||||||
out() << "}";
|
)~~~");
|
||||||
|
|
||||||
// Implementation: impl_from()
|
|
||||||
if (!interface.attributes.is_empty() || !interface.functions.is_empty()) {
|
if (!interface.attributes.is_empty() || !interface.functions.is_empty()) {
|
||||||
out() << "static " << interface.fully_qualified_name << "* impl_from(JS::VM& vm, JS::GlobalObject& global_object)";
|
generator.append(R"~~~(
|
||||||
out() << "{";
|
static @fully_qualified_name@* impl_from(JS::VM& vm, JS::GlobalObject& global_object)
|
||||||
out() << " auto* this_object = vm.this_value(global_object).to_object(global_object);";
|
{
|
||||||
out() << " if (!this_object)";
|
auto* this_object = vm.this_value(global_object).to_object(global_object);
|
||||||
out() << " return {};";
|
if (!this_object)
|
||||||
out() << " if (!this_object->inherits(\"" << wrapper_class << "\")) {";
|
return {};
|
||||||
out() << " vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotA, \"" << interface.fully_qualified_name << "\");";
|
if (!this_object->inherits("@wrapper_class@")) {
|
||||||
out() << " return nullptr;";
|
vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotA, "@fully_qualified_name@");
|
||||||
out() << " }";
|
return nullptr;
|
||||||
out() << " return &static_cast<" << wrapper_class << "*>(this_object)->impl();";
|
|
||||||
out() << "}";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto generate_to_cpp = [&](auto& parameter, auto& js_name, auto& js_suffix, auto cpp_name, bool return_void = false) {
|
return &static_cast<@wrapper_class@*>(this_object)->impl();
|
||||||
auto generate_return = [&] {
|
}
|
||||||
if (return_void)
|
)~~~");
|
||||||
out() << " return;";
|
}
|
||||||
else
|
|
||||||
out() << " return {};";
|
auto generate_to_cpp = [&](auto& parameter, auto& js_name, const auto& js_suffix, auto cpp_name, bool return_void = false) {
|
||||||
};
|
auto scoped_generator = generator.fork();
|
||||||
|
scoped_generator.set("cpp_name", cpp_name);
|
||||||
|
scoped_generator.set("js_name", js_name);
|
||||||
|
scoped_generator.set("js_suffix", js_suffix);
|
||||||
|
scoped_generator.set("parameter.type.name", parameter.type.name);
|
||||||
|
|
||||||
|
if (return_void)
|
||||||
|
scoped_generator.set("return_statement", "return;");
|
||||||
|
else
|
||||||
|
scoped_generator.set("return_statement", "return {};");
|
||||||
|
|
||||||
if (parameter.type.name == "DOMString") {
|
if (parameter.type.name == "DOMString") {
|
||||||
out() << " auto " << cpp_name << " = " << js_name << js_suffix << ".to_string(global_object);";
|
scoped_generator.append(R"~~~(
|
||||||
out() << " if (vm.exception())";
|
auto @cpp_name@ = @js_name@@js_suffix@.to_string(global_object);
|
||||||
generate_return();
|
if (vm.exception())
|
||||||
|
@return_statement@
|
||||||
|
)~~~");
|
||||||
} else if (parameter.type.name == "EventListener") {
|
} else if (parameter.type.name == "EventListener") {
|
||||||
out() << " if (!" << js_name << js_suffix << ".is_function()) {";
|
scoped_generator.append(R"~~~(
|
||||||
out() << " vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotA, \"Function\");";
|
if (!@js_name@@js_suffix@.is_function()) {
|
||||||
generate_return();
|
vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotA, "Function");
|
||||||
out() << " }";
|
@return_statement@
|
||||||
out() << " auto " << cpp_name << " = adopt(*new EventListener(JS::make_handle(&" << js_name << js_suffix << ".as_function())));";
|
}
|
||||||
|
auto @cpp_name@ = adopt(*new EventListener(JS::make_handle(&@js_name@@js_suffix@.as_function())));
|
||||||
|
)~~~");
|
||||||
} else if (is_wrappable_type(parameter.type)) {
|
} else if (is_wrappable_type(parameter.type)) {
|
||||||
out() << " auto " << cpp_name << "_object = " << js_name << js_suffix << ".to_object(global_object);";
|
scoped_generator.append(R"~~~(
|
||||||
out() << " if (vm.exception())";
|
auto @cpp_name@_object = @js_name@@js_suffix@.to_object(global_object);
|
||||||
generate_return();
|
if (vm.exception())
|
||||||
out() << " if (!" << cpp_name << "_object->inherits(\"" << parameter.type.name << "Wrapper\")) {";
|
@return_statement@
|
||||||
out() << " vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotA, \"" << parameter.type.name << "\");";
|
|
||||||
generate_return();
|
if (!@cpp_name@_object->inherits("@parameter.type.name@Wrapper")) {
|
||||||
out() << " }";
|
vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotA, "@parameter.type.name@");
|
||||||
out() << " auto& " << cpp_name << " = static_cast<" << parameter.type.name << "Wrapper*>(" << cpp_name << "_object)->impl();";
|
@return_statement@
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& @cpp_name@ = static_cast<@parameter.type.name@Wrapper*>(@cpp_name@_object)->impl();
|
||||||
|
)~~~");
|
||||||
} else if (parameter.type.name == "double") {
|
} else if (parameter.type.name == "double") {
|
||||||
out() << " auto " << cpp_name << " = " << js_name << js_suffix << ".to_double(global_object);";
|
scoped_generator.append(R"~~~(
|
||||||
out() << " if (vm.exception())";
|
auto @cpp_name@ = @js_name@@js_suffix@.to_double(global_object);
|
||||||
generate_return();
|
if (vm.exception())
|
||||||
|
@return_statement@
|
||||||
|
)~~~");
|
||||||
} else if (parameter.type.name == "boolean") {
|
} else if (parameter.type.name == "boolean") {
|
||||||
out() << " auto " << cpp_name << " = " << js_name << js_suffix << ".to_boolean();";
|
scoped_generator.append(R"~~~(
|
||||||
|
auto @cpp_name@ = @js_name@@js_suffix@.to_boolean();
|
||||||
|
)~~~");
|
||||||
} else {
|
} else {
|
||||||
dbg() << "Unimplemented JS-to-C++ conversion: " << parameter.type.name;
|
dbgln("Unimplemented JS-to-C++ conversion: {}", parameter.type.name);
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
auto generate_arguments = [&](auto& parameters, auto& arguments_builder, bool return_void = false) {
|
auto generate_arguments = [&](auto& parameters, auto& arguments_builder, bool return_void = false) {
|
||||||
|
auto arguments_generator = generator.fork();
|
||||||
|
|
||||||
Vector<String> parameter_names;
|
Vector<String> parameter_names;
|
||||||
size_t argument_index = 0;
|
size_t argument_index = 0;
|
||||||
for (auto& parameter : parameters) {
|
for (auto& parameter : parameters) {
|
||||||
parameter_names.append(snake_name(parameter.name));
|
parameter_names.append(snake_name(parameter.name));
|
||||||
out() << " auto arg" << argument_index << " = vm.argument(" << argument_index << ");";
|
arguments_generator.set("argument.index", String::number(argument_index));
|
||||||
generate_to_cpp(parameter, "arg", argument_index, snake_name(parameter.name), return_void);
|
|
||||||
|
arguments_generator.append(R"~~~(
|
||||||
|
auto arg@argument.index@ = vm.argument(@argument.index@);
|
||||||
|
)~~~");
|
||||||
|
generate_to_cpp(parameter, "arg", String::number(argument_index), snake_name(parameter.name), return_void);
|
||||||
++argument_index;
|
++argument_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -568,126 +669,200 @@ void generate_implementation(const IDL::Interface& interface)
|
||||||
};
|
};
|
||||||
|
|
||||||
auto generate_return_statement = [&](auto& return_type) {
|
auto generate_return_statement = [&](auto& return_type) {
|
||||||
|
auto scoped_generator = generator.fork();
|
||||||
|
scoped_generator.set("return_type", return_type.name);
|
||||||
|
|
||||||
if (return_type.name == "void") {
|
if (return_type.name == "void") {
|
||||||
out() << " return JS::js_undefined();";
|
scoped_generator.append(R"~~~(
|
||||||
|
return JS::js_undefined();
|
||||||
|
)~~~");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (return_type.nullable) {
|
if (return_type.nullable) {
|
||||||
if (return_type.name == "DOMString") {
|
if (return_type.name == "DOMString") {
|
||||||
out() << " if (retval.is_null())";
|
scoped_generator.append(R"~~~(
|
||||||
|
if (retval.is_null())
|
||||||
|
return JS::js_null();
|
||||||
|
)~~~");
|
||||||
} else {
|
} else {
|
||||||
out() << " if (!retval)";
|
scoped_generator.append(R"~~~(
|
||||||
|
if (!retval)
|
||||||
|
return JS::js_null();
|
||||||
|
)~~~");
|
||||||
}
|
}
|
||||||
out() << " return JS::js_null();";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (return_type.name == "DOMString") {
|
if (return_type.name == "DOMString") {
|
||||||
out() << " return JS::js_string(vm, retval);";
|
scoped_generator.append(R"~~~(
|
||||||
|
return JS::js_string(vm, retval);
|
||||||
|
)~~~");
|
||||||
} else if (return_type.name == "ArrayFromVector") {
|
} else if (return_type.name == "ArrayFromVector") {
|
||||||
// FIXME: Remove this fake type hack once it's no longer needed.
|
// FIXME: Remove this fake type hack once it's no longer needed.
|
||||||
// Basically once we have NodeList we can throw this out.
|
// Basically once we have NodeList we can throw this out.
|
||||||
out() << " auto* new_array = JS::Array::create(global_object);";
|
scoped_generator.append(R"~~~(
|
||||||
out() << " for (auto& element : retval) {";
|
auto* new_array = JS::Array::create(global_object);
|
||||||
out() << " new_array->indexed_properties().append(wrap(global_object, element));";
|
for (auto& element : retval)
|
||||||
out() << " }";
|
new_array->indexed_properties().append(wrap(global_object, element));
|
||||||
out() << " return new_array;";
|
|
||||||
} else if (return_type.name == "long" || return_type.name == "double") {
|
return new_array;
|
||||||
out() << " return JS::Value(retval);";
|
)~~~");
|
||||||
|
} else if (return_type.name == "long" || return_type.name == "double" || return_type.name == "boolean") {
|
||||||
|
scoped_generator.append(R"~~~(
|
||||||
|
return JS::Value(retval);
|
||||||
|
)~~~");
|
||||||
} else if (return_type.name == "Uint8ClampedArray") {
|
} else if (return_type.name == "Uint8ClampedArray") {
|
||||||
out() << " return retval;";
|
scoped_generator.append(R"~~~(
|
||||||
} else if (return_type.name == "boolean") {
|
return retval;
|
||||||
out() << " return JS::Value(retval);";
|
)~~~");
|
||||||
} else {
|
} else {
|
||||||
out() << " return wrap(global_object, const_cast<" << return_type.name << "&>(*retval));";
|
scoped_generator.append(R"~~~(
|
||||||
|
return wrap(global_object, const_cast<@return_type@&>(*retval));
|
||||||
|
)~~~");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Implementation: Attributes
|
|
||||||
for (auto& attribute : interface.attributes) {
|
for (auto& attribute : interface.attributes) {
|
||||||
out() << "JS_DEFINE_NATIVE_GETTER(" << wrapper_class << "::" << attribute.getter_callback_name << ")";
|
auto attribute_generator = generator.fork();
|
||||||
out() << "{";
|
attribute_generator.set("attribute.getter_callback", attribute.getter_callback_name);
|
||||||
out() << " auto* impl = impl_from(vm, global_object);";
|
attribute_generator.set("attribute.setter_callback", attribute.setter_callback_name);
|
||||||
out() << " if (!impl)";
|
attribute_generator.set("attribute.name:snakecase", snake_name(attribute.name));
|
||||||
out() << " return {};";
|
|
||||||
|
|
||||||
if (attribute.extended_attributes.contains("ReturnNullIfCrossOrigin")) {
|
|
||||||
out() << " if (!impl->may_access_from_origin(static_cast<WindowObject&>(global_object).origin()))";
|
|
||||||
out() << " return JS::js_null();";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attribute.extended_attributes.contains("Reflect")) {
|
if (attribute.extended_attributes.contains("Reflect")) {
|
||||||
auto attribute_name = attribute.extended_attributes.get("Reflect").value();
|
auto attribute_name = attribute.extended_attributes.get("Reflect").value();
|
||||||
if (attribute_name.is_null())
|
if (attribute_name.is_null())
|
||||||
attribute_name = attribute.name;
|
attribute_name = attribute.name;
|
||||||
attribute_name = make_input_acceptable_cpp(attribute_name);
|
attribute_name = make_input_acceptable_cpp(attribute_name);
|
||||||
out() << " auto retval = impl->attribute(HTML::AttributeNames::" << attribute_name << ");";
|
|
||||||
|
attribute_generator.set("attribute.reflect_name", attribute_name);
|
||||||
} else {
|
} else {
|
||||||
out() << " auto retval = impl->" << snake_name(attribute.name) << "();";
|
attribute_generator.set("attribute.reflect_name", snake_name(attribute.name));
|
||||||
|
}
|
||||||
|
|
||||||
|
attribute_generator.append(R"~~~(
|
||||||
|
JS_DEFINE_NATIVE_GETTER(@wrapper_class@::@attribute.getter_callback@)
|
||||||
|
{
|
||||||
|
auto* impl = impl_from(vm, global_object);
|
||||||
|
if (!impl)
|
||||||
|
return {};
|
||||||
|
)~~~");
|
||||||
|
|
||||||
|
if (attribute.extended_attributes.contains("ReturnNullIfCrossOrigin")) {
|
||||||
|
attribute_generator.append(R"~~~(
|
||||||
|
if (!impl->may_access_from_origin(static_cast<WindowObject&>(global_object).origin()))
|
||||||
|
return JS::js_null();
|
||||||
|
)~~~");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attribute.extended_attributes.contains("Reflect")) {
|
||||||
|
attribute_generator.append(R"~~~(
|
||||||
|
auto retval = impl->attribute(HTML::AttributeNames::@attribute.reflect_name@);
|
||||||
|
)~~~");
|
||||||
|
} else {
|
||||||
|
attribute_generator.append(R"~~~(
|
||||||
|
auto retval = impl->@attribute.name:snakecase@();
|
||||||
|
)~~~");
|
||||||
}
|
}
|
||||||
|
|
||||||
generate_return_statement(attribute.type);
|
generate_return_statement(attribute.type);
|
||||||
out() << "}";
|
|
||||||
|
attribute_generator.append(R"~~~(
|
||||||
|
}
|
||||||
|
)~~~");
|
||||||
|
|
||||||
if (!attribute.readonly) {
|
if (!attribute.readonly) {
|
||||||
out() << "JS_DEFINE_NATIVE_SETTER(" << wrapper_class << "::" << attribute.setter_callback_name << ")";
|
attribute_generator.append(R"~~~(
|
||||||
out() << "{";
|
JS_DEFINE_NATIVE_SETTER(@wrapper_class@::@attribute.setter_callback@)
|
||||||
out() << " auto* impl = impl_from(vm, global_object);";
|
{
|
||||||
out() << " if (!impl)";
|
auto* impl = impl_from(vm, global_object);
|
||||||
out() << " return;";
|
if (!impl)
|
||||||
|
return;
|
||||||
|
)~~~");
|
||||||
|
|
||||||
generate_to_cpp(attribute, "value", "", "cpp_value", true);
|
generate_to_cpp(attribute, "value", "", "cpp_value", true);
|
||||||
|
|
||||||
if (attribute.extended_attributes.contains("Reflect")) {
|
if (attribute.extended_attributes.contains("Reflect")) {
|
||||||
auto attribute_name = attribute.extended_attributes.get("Reflect").value();
|
attribute_generator.append(R"~~~(
|
||||||
if (attribute_name.is_null())
|
impl->set_attribute(HTML::AttributeNames::@attribute.reflect_name@, cpp_value);
|
||||||
attribute_name = attribute.name;
|
)~~~");
|
||||||
attribute_name = make_input_acceptable_cpp(attribute_name);
|
|
||||||
out() << " impl->set_attribute(HTML::AttributeNames::" << attribute_name << ", cpp_value);";
|
|
||||||
} else {
|
} else {
|
||||||
out() << " impl->set_" << snake_name(attribute.name) << "(cpp_value);";
|
attribute_generator.append(R"~~~(
|
||||||
|
impl->set_@attribute.name:snakecase@(cpp_value);
|
||||||
|
)~~~");
|
||||||
}
|
}
|
||||||
out() << "}";
|
|
||||||
|
attribute_generator.append(R"~~~(
|
||||||
|
}
|
||||||
|
)~~~");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implementation: Functions
|
// Implementation: Functions
|
||||||
for (auto& function : interface.functions) {
|
for (auto& function : interface.functions) {
|
||||||
out() << "JS_DEFINE_NATIVE_FUNCTION(" << wrapper_class << "::" << snake_name(function.name) << ")";
|
auto function_generator = generator.fork();
|
||||||
out() << "{";
|
function_generator.set("function.name", function.name);
|
||||||
out() << " auto* impl = impl_from(vm, global_object);";
|
function_generator.set("function.name:snakecase", snake_name(function.name));
|
||||||
out() << " if (!impl)";
|
function_generator.set("function.nargs", String::number(function.length()));
|
||||||
out() << " return {};";
|
|
||||||
|
function_generator.append(R"~~~(\
|
||||||
|
JS_DEFINE_NATIVE_FUNCTION(@wrapper_class@::@function.name:snakecase@)
|
||||||
|
{
|
||||||
|
auto* impl = impl_from(vm, global_object);
|
||||||
|
if (!impl)
|
||||||
|
return {};
|
||||||
|
)~~~");
|
||||||
|
|
||||||
if (function.length() > 0) {
|
if (function.length() > 0) {
|
||||||
out() << " if (vm.argument_count() < " << function.length() << ") {";
|
if (function.length() == 1) {
|
||||||
if (function.length() == 1)
|
function_generator.set(".bad_arg_count", "JS::ErrorType::BadArgCountOne");
|
||||||
out() << " vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountOne, \"" << function.name << "\");";
|
function_generator.set(".arg_count_suffix", "");
|
||||||
else
|
} else {
|
||||||
out() << " vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountMany, \"" << function.name << "\", \"" << function.length() << "\");";
|
function_generator.set(".bad_arg_count", "JS::ErrorType::BadArgCountMany");
|
||||||
out() << " return {};";
|
function_generator.set(".arg_count_suffix", String::formatted(", \"{}\"", function.length()));
|
||||||
out() << " }";
|
}
|
||||||
|
|
||||||
|
function_generator.append(R"~~~(
|
||||||
|
if (vm.argument_count() < @function.nargs@) {
|
||||||
|
vm.throw_exception<JS::TypeError>(global_object, @.bad_arg_count@, "@function.name@"@.arg_count_suffix@);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
)~~~");
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder arguments_builder;
|
StringBuilder arguments_builder;
|
||||||
generate_arguments(function.parameters, arguments_builder);
|
generate_arguments(function.parameters, arguments_builder);
|
||||||
|
|
||||||
|
function_generator.set(".arguments", arguments_builder.string_view());
|
||||||
|
|
||||||
if (function.return_type.name != "void") {
|
if (function.return_type.name != "void") {
|
||||||
out() << " auto retval = impl->" << snake_name(function.name) << "(" << arguments_builder.to_string() << ");";
|
function_generator.append(R"~~~(
|
||||||
|
auto retval = impl->@function.name:snakecase@(@.arguments@);
|
||||||
|
)~~~");
|
||||||
} else {
|
} else {
|
||||||
out() << " impl->" << snake_name(function.name) << "(" << arguments_builder.to_string() << ");";
|
function_generator.append(R"~~~(
|
||||||
|
impl->@function.name:snakecase@(@.arguments@);
|
||||||
|
)~~~");
|
||||||
}
|
}
|
||||||
|
|
||||||
generate_return_statement(function.return_type);
|
generate_return_statement(function.return_type);
|
||||||
out() << "}";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implementation: Wrapper factory
|
function_generator.append(R"~~~(
|
||||||
if (should_emit_wrapper_factory(interface)) {
|
}
|
||||||
out() << wrapper_class << "* wrap(JS::GlobalObject& global_object, " << interface.fully_qualified_name << "& impl)";
|
)~~~");
|
||||||
out() << "{";
|
}
|
||||||
out() << " return static_cast<" << wrapper_class << "*>(wrap_impl(global_object, impl));";
|
|
||||||
out() << "}";
|
if (should_emit_wrapper_factory(interface)) {
|
||||||
}
|
generator.append(R"~~~(
|
||||||
|
@wrapper_class@* wrap(JS::GlobalObject& global_object, @fully_qualified_name@& impl)
|
||||||
out() << "}";
|
{
|
||||||
|
return static_cast<@wrapper_class@*>(wrap_impl(global_object, impl));
|
||||||
|
}
|
||||||
|
)~~~");
|
||||||
|
}
|
||||||
|
|
||||||
|
generator.append(R"~~~(
|
||||||
|
} // namespace Web::Bindings
|
||||||
|
)~~~");
|
||||||
|
|
||||||
|
outln("{}", generator.as_string_view());
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,6 @@ int main(int argc, char** argv)
|
||||||
args_parser.add_positional_argument(path, "Path", "path");
|
args_parser.add_positional_argument(path, "Path", "path");
|
||||||
args_parser.parse(argc, argv);
|
args_parser.parse(argc, argv);
|
||||||
|
|
||||||
out() << LexicalPath(path).dirname().characters();
|
outln("{}", LexicalPath(path).dirname());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,7 +126,7 @@ int main(int argc, char** argv)
|
||||||
if (current_symbol < symbols.end() && !current_symbol->contains(virtual_offset)) {
|
if (current_symbol < symbols.end() && !current_symbol->contains(virtual_offset)) {
|
||||||
if (!is_first_symbol && current_instruction_is_in_symbol) {
|
if (!is_first_symbol && current_instruction_is_in_symbol) {
|
||||||
// The previous instruction was part of a symbol that doesn't cover the current instruction, so separate it from the current instruction with a newline.
|
// The previous instruction was part of a symbol that doesn't cover the current instruction, so separate it from the current instruction with a newline.
|
||||||
out();
|
outln();
|
||||||
current_instruction_is_in_symbol = (current_symbol + 1 < symbols.end() && (current_symbol + 1)->contains(virtual_offset));
|
current_instruction_is_in_symbol = (current_symbol + 1 < symbols.end() && (current_symbol + 1)->contains(virtual_offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,21 +134,19 @@ int main(int argc, char** argv)
|
||||||
while (current_symbol + 1 < symbols.end() && !(current_symbol + 1)->contains(virtual_offset) && (current_symbol + 1)->address() <= virtual_offset) {
|
while (current_symbol + 1 < symbols.end() && !(current_symbol + 1)->contains(virtual_offset) && (current_symbol + 1)->address() <= virtual_offset) {
|
||||||
++current_symbol;
|
++current_symbol;
|
||||||
if (!is_first_symbol)
|
if (!is_first_symbol)
|
||||||
out() << "\n(" << current_symbol->name << " (" << String::format("%08x-%08x", current_symbol->address(), current_symbol->address_end()) << "))\n";
|
outln("\n({} ({:p}-{:p}))\n", current_symbol->name, current_symbol->address(), current_symbol->address_end());
|
||||||
}
|
}
|
||||||
while (current_symbol + 1 < symbols.end() && (current_symbol + 1)->contains(virtual_offset)) {
|
while (current_symbol + 1 < symbols.end() && (current_symbol + 1)->contains(virtual_offset)) {
|
||||||
if (!is_first_symbol && !current_instruction_is_in_symbol)
|
if (!is_first_symbol && !current_instruction_is_in_symbol)
|
||||||
out();
|
outln();
|
||||||
++current_symbol;
|
++current_symbol;
|
||||||
current_instruction_is_in_symbol = true;
|
current_instruction_is_in_symbol = true;
|
||||||
out() << current_symbol->name << " (" << String::format("%08x-%08x", current_symbol->address(), current_symbol->address_end()) << "):";
|
outln("{} ({:p}-{:p}):", current_symbol->name, current_symbol->address(), current_symbol->address_end());
|
||||||
}
|
}
|
||||||
|
|
||||||
is_first_symbol = false;
|
is_first_symbol = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
out() << String::format("%08x", virtual_offset) << " " << insn.value().to_string(virtual_offset, symbol_provider);
|
outln("{:p} {}", virtual_offset, insn.value().to_string(virtual_offset, symbol_provider));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,7 @@ int main(int argc, char** argv)
|
||||||
}
|
}
|
||||||
for (; !tar_stream.finished(); tar_stream.advance()) {
|
for (; !tar_stream.finished(); tar_stream.advance()) {
|
||||||
if (list || verbose)
|
if (list || verbose)
|
||||||
out() << tar_stream.header().file_name();
|
outln("{}", tar_stream.header().file_name());
|
||||||
|
|
||||||
if (extract) {
|
if (extract) {
|
||||||
Tar::TarFileStream file_stream = tar_stream.file_contents();
|
Tar::TarFileStream file_stream = tar_stream.file_contents();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue