summaryrefslogtreecommitdiff
path: root/Meta
diff options
context:
space:
mode:
authorIdan Horowitz <idan.horowitz@gmail.com>2021-09-13 00:27:13 +0300
committerAndreas Kling <kling@serenityos.org>2021-09-13 01:43:10 +0200
commit2b78e227f2bba96ebdf10f5aa0a83e0c9fd022cb (patch)
tree7de600df88f8fb76106bb05c6a066a5816530b37 /Meta
parent47e261c691af0fa09f4522fd9ac43d6f94a35732 (diff)
downloadserenity-2b78e227f2bba96ebdf10f5aa0a83e0c9fd022cb.zip
LibWeb: Add support for generating a stringifier method/attribute
Diffstat (limited to 'Meta')
-rw-r--r--Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator.cpp68
1 files changed, 67 insertions, 1 deletions
diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator.cpp
index 998aac94cb..7929915f55 100644
--- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator.cpp
+++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator.cpp
@@ -136,6 +136,8 @@ struct Interface {
Vector<Constructor> constructors;
Vector<Function> functions;
Vector<Function> static_functions;
+ bool has_stringifier { false };
+ Optional<String> stringifier_attribute;
// Added for convenience after parsing
String wrapper_class;
@@ -333,6 +335,16 @@ static OwnPtr<Interface> parse_interface(StringView filename, StringView const&
interface->constructors.append(Constructor { interface->name, move(parameters) });
};
+ auto parse_stringifier = [&](HashMap<String, String>& extended_attributes) {
+ assert_string("stringifier");
+ interface->has_stringifier = true;
+ if (lexer.next_is("readonly") || lexer.next_is("attribute")) {
+ parse_attribute(extended_attributes);
+ interface->stringifier_attribute = interface->attributes.last().name;
+ }
+ assert_specific(';');
+ };
+
for (;;) {
HashMap<String, String> extended_attributes;
@@ -358,6 +370,11 @@ static OwnPtr<Interface> parse_interface(StringView filename, StringView const&
continue;
}
+ if (lexer.next_is("stringifier")) {
+ parse_stringifier(extended_attributes);
+ continue;
+ }
+
if (lexer.next_is("readonly") || lexer.next_is("attribute")) {
parse_attribute(extended_attributes);
continue;
@@ -1378,6 +1395,13 @@ private:
)~~~");
}
+ if (interface.has_stringifier) {
+ auto stringifier_generator = generator.fork();
+ stringifier_generator.append(R"~~~(
+ JS_DECLARE_NATIVE_FUNCTION(to_string);
+ )~~~");
+ }
+
for (auto& attribute : interface.attributes) {
auto attribute_generator = generator.fork();
attribute_generator.set("attribute.name:snakecase", attribute.name.to_snakecase());
@@ -1565,12 +1589,19 @@ void @prototype_class@::initialize(JS::GlobalObject& global_object)
)~~~");
}
+ if (interface.has_stringifier) {
+ auto stringifier_generator = generator.fork();
+ stringifier_generator.append(R"~~~(
+ define_native_function("toString", to_string, 0, default_attributes);
+)~~~");
+ }
+
generator.append(R"~~~(
Object::initialize(global_object);
}
)~~~");
- if (!interface.attributes.is_empty() || !interface.functions.is_empty()) {
+ if (!interface.attributes.is_empty() || !interface.functions.is_empty() || interface.has_stringifier) {
generator.append(R"~~~(
static @fully_qualified_name@* impl_from(JS::VM& vm, JS::GlobalObject& global_object)
{
@@ -1703,6 +1734,41 @@ JS_DEFINE_NATIVE_FUNCTION(@prototype_class@::@attribute.setter_callback@)
generate_function(generator, function, StaticFunction::No, interface.prototype_class, interface.fully_qualified_name);
}
+ if (interface.has_stringifier) {
+ auto stringifier_generator = generator.fork();
+ stringifier_generator.set("class_name", interface.prototype_class);
+ if (interface.stringifier_attribute.has_value())
+ stringifier_generator.set("attribute.cpp_getter_name", interface.stringifier_attribute->to_snakecase());
+
+ stringifier_generator.append(R"~~~(
+JS_DEFINE_NATIVE_FUNCTION(@class_name@::to_string)
+{
+ auto* impl = impl_from(vm, global_object);
+ if (!impl)
+ return {};
+
+)~~~");
+ if (interface.stringifier_attribute.has_value()) {
+ stringifier_generator.append(R"~~~(
+ auto retval = impl->@attribute.cpp_getter_name@();
+)~~~");
+ } else {
+ stringifier_generator.append(R"~~~(
+ auto result = throw_dom_exception_if_needed(vm, global_object, [&] { return impl->to_string(); });
+
+ if (should_return_empty(result))
+ return JS::Value();
+
+ auto retval = result.release_value();
+)~~~");
+ }
+ stringifier_generator.append(R"~~~(
+
+ return JS::js_string(vm, move(retval));
+}
+)~~~");
+ }
+
generator.append(R"~~~(
} // namespace Web::Bindings
)~~~");