mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 16:02:45 +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&) { | ||||
|         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&) { | ||||
|  |  | |||
|  | @ -25,6 +25,7 @@ | |||
|  */ | ||||
| 
 | ||||
| #include <AK/JsonObject.h> | ||||
| #include <AK/SourceGenerator.h> | ||||
| #include <AK/StringBuilder.h> | ||||
| #include <LibCore/File.h> | ||||
| #include <ctype.h> | ||||
|  | @ -48,7 +49,7 @@ static String title_casify(const String& dashy_name) | |||
| int main(int argc, char** argv) | ||||
| { | ||||
|     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; | ||||
|     } | ||||
|     auto file = Core::File::construct(argv[1]); | ||||
|  | @ -59,34 +60,59 @@ int main(int argc, char** argv) | |||
|     ASSERT(json.has_value()); | ||||
|     ASSERT(json.value().is_object()); | ||||
| 
 | ||||
|     out() << "#include <AK/Assertions.h>"; | ||||
|     out() << "#include <LibWeb/CSS/PropertyID.h>"; | ||||
|     out() << "namespace Web::CSS {"; | ||||
|     StringBuilder builder; | ||||
|     SourceGenerator generator { builder }; | ||||
| 
 | ||||
|     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) { | ||||
|         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;"; | ||||
| 
 | ||||
|     out() << "}"; | ||||
| 
 | ||||
|     out() << "const char* string_from_property_id(PropertyID property_id) {"; | ||||
|     out() << "    switch (property_id) {"; | ||||
|     json.value().as_object().for_each_member([&](auto& name, auto& value) { | ||||
|         ASSERT(value.is_object()); | ||||
|         out() << "    case PropertyID::" << title_casify(name) << ":"; | ||||
|         out() << "        return \"" << name << "\";"; | ||||
|     }); | ||||
|     out() << "    default:"; | ||||
|     out() << "        return \"(invalid CSS::PropertyID)\";"; | ||||
|     out() << "    }"; | ||||
|     out() << "}"; | ||||
|     out() << "}"; | ||||
| 
 | ||||
|     return 0; | ||||
|     generator.append(R"~~~( | ||||
|     return PropertyID::Invalid; | ||||
| } | ||||
| 
 | ||||
| const char* string_from_property_id(PropertyID property_id) { | ||||
|     switch (property_id) { | ||||
| )~~~"); | ||||
| 
 | ||||
|     json.value().as_object().for_each_member([&](auto& name, auto& value) { | ||||
|         ASSERT(value.is_object()); | ||||
| 
 | ||||
|         auto member_generator = generator.fork(); | ||||
|         member_generator.set("name", name); | ||||
|         member_generator.set("name:titlecase", title_casify(name)); | ||||
|         member_generator.append(R"~~~( | ||||
|     case PropertyID::@name:titlecase@: | ||||
|         return "@name@"; | ||||
|         )~~~"); | ||||
|     }); | ||||
| 
 | ||||
|     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/SourceGenerator.h> | ||||
| #include <AK/StringBuilder.h> | ||||
| #include <LibCore/File.h> | ||||
| #include <ctype.h> | ||||
|  | @ -48,7 +49,7 @@ static String title_casify(const String& dashy_name) | |||
| int main(int argc, char** argv) | ||||
| { | ||||
|     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; | ||||
|     } | ||||
|     auto file = Core::File::construct(argv[1]); | ||||
|  | @ -59,30 +60,46 @@ int main(int argc, char** argv) | |||
|     ASSERT(json.has_value()); | ||||
|     ASSERT(json.value().is_object()); | ||||
| 
 | ||||
|     out() << "#pragma once"; | ||||
|     out() << "#include <AK/StringView.h>"; | ||||
|     out() << "#include <AK/Traits.h>"; | ||||
|     StringBuilder builder; | ||||
|     SourceGenerator generator { builder }; | ||||
|     generator.append(R"~~~( | ||||
| #pragma once | ||||
| 
 | ||||
|     out() << "namespace Web::CSS {"; | ||||
|     out() << "enum class PropertyID {"; | ||||
|     out() << "    Invalid,"; | ||||
| #include <AK/StringView.h> | ||||
| #include <AK/Traits.h> | ||||
| 
 | ||||
| namespace Web::CSS { | ||||
| 
 | ||||
| enum class PropertyID { | ||||
|     Invalid, | ||||
| )~~~"); | ||||
| 
 | ||||
|     json.value().as_object().for_each_member([&](auto& name, auto& value) { | ||||
|         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\
 | ||||
| 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"; | ||||
|     generator.append(R"~~~( | ||||
| }; | ||||
| 
 | ||||
|     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/HashMap.h> | ||||
| #include <AK/LexicalPath.h> | ||||
| #include <AK/SourceGenerator.h> | ||||
| #include <AK/StringBuilder.h> | ||||
| #include <LibCore/ArgsParser.h> | ||||
| #include <LibCore/File.h> | ||||
|  | @ -286,7 +287,7 @@ int main(int argc, char** argv) | |||
|     auto interface = IDL::parse_interface(data); | ||||
| 
 | ||||
|     if (!interface) { | ||||
|         fprintf(stderr, "Cannot parse %s\n", path); | ||||
|         warnln("Cannot parse {}", path); | ||||
|         return 1; | ||||
|     } | ||||
| 
 | ||||
|  | @ -366,201 +367,301 @@ static bool is_wrappable_type(const IDL::Type& type) | |||
| 
 | ||||
| static void generate_header(const IDL::Interface& interface) | ||||
| { | ||||
|     auto& wrapper_class = interface.wrapper_class; | ||||
|     auto& wrapper_base_class = interface.wrapper_base_class; | ||||
|     StringBuilder builder; | ||||
|     SourceGenerator generator { builder }; | ||||
| 
 | ||||
|     out() << "#pragma once"; | ||||
|     out() << "#include <LibWeb/Bindings/Wrapper.h>"; | ||||
|     generator.set("name", interface.name); | ||||
|     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.
 | ||||
|     out() << "#if __has_include(<LibWeb/DOM/" << interface.name << ".h>)"; | ||||
|     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"; | ||||
|     generator.append(R"~~~( | ||||
| #pragma once | ||||
| 
 | ||||
|     if (wrapper_base_class != "Wrapper") | ||||
|         out() << "#include <LibWeb/Bindings/" << wrapper_base_class << ".h>"; | ||||
| #include <LibWeb/Bindings/Wrapper.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 << " {"; | ||||
|     out() << "    JS_OBJECT(" << wrapper_class << ", " << wrapper_base_class << ");"; | ||||
|     out() << "public:"; | ||||
|     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()); }"; | ||||
|     if (interface.wrapper_base_class != "Wrapper") { | ||||
|         generator.append(R"~~~( | ||||
| #include <LibWeb/Bindings/@wrapper_base_class@.h> | ||||
| )~~~"); | ||||
|     } | ||||
| 
 | ||||
|     auto is_foo_wrapper_name = snake_name(String::format("Is%s", wrapper_class.characters())); | ||||
|     out() << "    virtual bool " << is_foo_wrapper_name << "() const final { return true; }"; | ||||
|     generator.append(R"~~~( | ||||
| 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) { | ||||
|         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) { | ||||
|         out() << "    JS_DECLARE_NATIVE_GETTER(" << snake_name(attribute.name) << "_getter);"; | ||||
|         if (!attribute.readonly) | ||||
|             out() << "    JS_DECLARE_NATIVE_SETTER(" << snake_name(attribute.name) << "_setter);"; | ||||
|         auto attribute_generator = generator.fork(); | ||||
|         attribute_generator.set("attribute.name:snakecase", snake_name(attribute.name)); | ||||
|         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") { | ||||
|         out() << "    NonnullRefPtr<" << interface.fully_qualified_name << "> m_impl;"; | ||||
|     if (interface.wrapper_base_class == "Wrapper") { | ||||
|         generator.append(R"~~~( | ||||
|     NonnullRefPtr<@fully_qualified_name@> m_impl; | ||||
|         )~~~"); | ||||
|     } | ||||
| 
 | ||||
|     out() << "};"; | ||||
|     generator.append(R"~~~( | ||||
| }; | ||||
| )~~~"); | ||||
| 
 | ||||
|     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) | ||||
| { | ||||
|     auto& wrapper_class = interface.wrapper_class; | ||||
|     auto& wrapper_base_class = interface.wrapper_base_class; | ||||
|     StringBuilder builder; | ||||
|     SourceGenerator generator { builder }; | ||||
| 
 | ||||
|     out() << "#include <AK/FlyString.h>"; | ||||
|     out() << "#include <LibJS/Runtime/Array.h>"; | ||||
|     out() << "#include <LibJS/Runtime/Value.h>"; | ||||
|     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>"; | ||||
|     generator.set("wrapper_class", interface.wrapper_class); | ||||
|     generator.set("wrapper_base_class", interface.wrapper_base_class); | ||||
|     generator.set("fully_qualified_name", interface.fully_qualified_name); | ||||
| 
 | ||||
|     // FIXME: This is a total hack until we can figure out the namespace for a given type somehow.
 | ||||
|     out() << "using namespace Web::DOM;"; | ||||
|     out() << "using namespace Web::HTML;"; | ||||
|     generator.append(R"~~~( | ||||
| #include <AK/FlyString.h> | ||||
| #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
 | ||||
|     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)"; | ||||
| namespace Web::Bindings { | ||||
| 
 | ||||
| )~~~"); | ||||
| 
 | ||||
|     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 { | ||||
|         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()
 | ||||
|     out() << "void " << wrapper_class << "::initialize(JS::GlobalObject& global_object)"; | ||||
|     out() << "{"; | ||||
|     out() << "    [[maybe_unused]] u8 default_attributes = JS::Attribute::Enumerable | JS::Attribute::Configurable;"; | ||||
|     out() << "    " << wrapper_base_class << "::initialize(global_object);"; | ||||
|     generator.append(R"~~~( | ||||
| void @wrapper_class@::initialize(JS::GlobalObject& global_object) | ||||
| { | ||||
|     [[maybe_unused]] u8 default_attributes = JS::Attribute::Enumerable | JS::Attribute::Configurable; | ||||
| 
 | ||||
|     @wrapper_base_class@::initialize(global_object); | ||||
| )~~~"); | ||||
| 
 | ||||
|     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) { | ||||
|         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
 | ||||
|     out() << wrapper_class << "::~" << wrapper_class << "()"; | ||||
|     out() << "{"; | ||||
|     out() << "}"; | ||||
| @wrapper_class@::~@wrapper_class@() | ||||
| { | ||||
| } | ||||
| )~~~"); | ||||
| 
 | ||||
|     // Implementation: impl_from()
 | ||||
|     if (!interface.attributes.is_empty() || !interface.functions.is_empty()) { | ||||
|         out() << "static " << interface.fully_qualified_name << "* impl_from(JS::VM& vm, JS::GlobalObject& global_object)"; | ||||
|         out() << "{"; | ||||
|         out() << "    auto* this_object = vm.this_value(global_object).to_object(global_object);"; | ||||
|         out() << "    if (!this_object)"; | ||||
|         out() << "        return {};"; | ||||
|         out() << "    if (!this_object->inherits(\"" << wrapper_class << "\")) {"; | ||||
|         out() << "        vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotA, \"" << interface.fully_qualified_name << "\");"; | ||||
|         out() << "        return nullptr;"; | ||||
|         out() << "    }"; | ||||
|         out() << "    return &static_cast<" << wrapper_class << "*>(this_object)->impl();"; | ||||
|         out() << "}"; | ||||
|         generator.append(R"~~~( | ||||
| static @fully_qualified_name@* impl_from(JS::VM& vm, JS::GlobalObject& global_object) | ||||
| { | ||||
|     auto* this_object = vm.this_value(global_object).to_object(global_object); | ||||
|     if (!this_object) | ||||
|         return {}; | ||||
|     if (!this_object->inherits("@wrapper_class@")) { | ||||
|         vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotA, "@fully_qualified_name@"); | ||||
|         return nullptr; | ||||
|     } | ||||
| 
 | ||||
|     auto generate_to_cpp = [&](auto& parameter, auto& js_name, auto& js_suffix, auto cpp_name, bool return_void = false) { | ||||
|         auto generate_return = [&] { | ||||
|     return &static_cast<@wrapper_class@*>(this_object)->impl(); | ||||
|     } | ||||
| )~~~"); | ||||
|     } | ||||
| 
 | ||||
|     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) | ||||
|                 out() << "        return;"; | ||||
|             scoped_generator.set("return_statement", "return;"); | ||||
|         else | ||||
|                 out() << "        return {};"; | ||||
|         }; | ||||
|             scoped_generator.set("return_statement", "return {};"); | ||||
| 
 | ||||
|         if (parameter.type.name == "DOMString") { | ||||
|             out() << "    auto " << cpp_name << " = " << js_name << js_suffix << ".to_string(global_object);"; | ||||
|             out() << "    if (vm.exception())"; | ||||
|             generate_return(); | ||||
|             scoped_generator.append(R"~~~( | ||||
|     auto @cpp_name@ = @js_name@@js_suffix@.to_string(global_object); | ||||
|     if (vm.exception()) | ||||
|         @return_statement@ | ||||
| )~~~"); | ||||
|         } else if (parameter.type.name == "EventListener") { | ||||
|             out() << "    if (!" << js_name << js_suffix << ".is_function()) {"; | ||||
|             out() << "        vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotA, \"Function\");"; | ||||
|             generate_return(); | ||||
|             out() << "    }"; | ||||
|             out() << "    auto " << cpp_name << " = adopt(*new EventListener(JS::make_handle(&" << js_name << js_suffix << ".as_function())));"; | ||||
|             scoped_generator.append(R"~~~( | ||||
|     if (!@js_name@@js_suffix@.is_function()) { | ||||
|         vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotA, "Function"); | ||||
|         @return_statement@ | ||||
|     } | ||||
|     auto @cpp_name@ = adopt(*new EventListener(JS::make_handle(&@js_name@@js_suffix@.as_function()))); | ||||
| )~~~"); | ||||
|         } else if (is_wrappable_type(parameter.type)) { | ||||
|             out() << "    auto " << cpp_name << "_object = " << js_name << js_suffix << ".to_object(global_object);"; | ||||
|             out() << "    if (vm.exception())"; | ||||
|             generate_return(); | ||||
|             out() << "    if (!" << cpp_name << "_object->inherits(\"" << parameter.type.name << "Wrapper\")) {"; | ||||
|             out() << "        vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotA, \"" << parameter.type.name << "\");"; | ||||
|             generate_return(); | ||||
|             out() << "    }"; | ||||
|             out() << "    auto& " << cpp_name << " = static_cast<" << parameter.type.name << "Wrapper*>(" << cpp_name << "_object)->impl();"; | ||||
|             scoped_generator.append(R"~~~( | ||||
|     auto @cpp_name@_object = @js_name@@js_suffix@.to_object(global_object); | ||||
|     if (vm.exception()) | ||||
|         @return_statement@ | ||||
| 
 | ||||
|     if (!@cpp_name@_object->inherits("@parameter.type.name@Wrapper")) { | ||||
|         vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotA, "@parameter.type.name@"); | ||||
|         @return_statement@ | ||||
|     } | ||||
| 
 | ||||
|     auto& @cpp_name@ = static_cast<@parameter.type.name@Wrapper*>(@cpp_name@_object)->impl(); | ||||
| )~~~"); | ||||
|         } else if (parameter.type.name == "double") { | ||||
|             out() << "    auto " << cpp_name << " = " << js_name << js_suffix << ".to_double(global_object);"; | ||||
|             out() << "    if (vm.exception())"; | ||||
|             generate_return(); | ||||
|             scoped_generator.append(R"~~~( | ||||
|     auto @cpp_name@ = @js_name@@js_suffix@.to_double(global_object); | ||||
|     if (vm.exception()) | ||||
|         @return_statement@ | ||||
| )~~~"); | ||||
|         } 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 { | ||||
|             dbg() << "Unimplemented JS-to-C++ conversion: " << parameter.type.name; | ||||
|             dbgln("Unimplemented JS-to-C++ conversion: {}", parameter.type.name); | ||||
|             ASSERT_NOT_REACHED(); | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     auto generate_arguments = [&](auto& parameters, auto& arguments_builder, bool return_void = false) { | ||||
|         auto arguments_generator = generator.fork(); | ||||
| 
 | ||||
|         Vector<String> parameter_names; | ||||
|         size_t argument_index = 0; | ||||
|         for (auto& parameter : parameters) { | ||||
|             parameter_names.append(snake_name(parameter.name)); | ||||
|             out() << "    auto arg" << argument_index << " = vm.argument(" << argument_index << ");"; | ||||
|             generate_to_cpp(parameter, "arg", argument_index, snake_name(parameter.name), return_void); | ||||
|             arguments_generator.set("argument.index", String::number(argument_index)); | ||||
| 
 | ||||
|             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; | ||||
|         } | ||||
| 
 | ||||
|  | @ -568,126 +669,200 @@ void generate_implementation(const IDL::Interface& interface) | |||
|     }; | ||||
| 
 | ||||
|     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") { | ||||
|             out() << "    return JS::js_undefined();"; | ||||
|             scoped_generator.append(R"~~~( | ||||
|     return JS::js_undefined(); | ||||
| )~~~"); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         if (return_type.nullable) { | ||||
|             if (return_type.name == "DOMString") { | ||||
|                 out() << "    if (retval.is_null())"; | ||||
|                 scoped_generator.append(R"~~~( | ||||
|     if (retval.is_null()) | ||||
|         return JS::js_null(); | ||||
| )~~~"); | ||||
|             } else { | ||||
|                 out() << "    if (!retval)"; | ||||
|                 scoped_generator.append(R"~~~( | ||||
|     if (!retval) | ||||
|         return JS::js_null(); | ||||
| )~~~"); | ||||
|             } | ||||
|             out() << "        return JS::js_null();"; | ||||
|         } | ||||
| 
 | ||||
|         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") { | ||||
|             // FIXME: Remove this fake type hack once it's no longer needed.
 | ||||
|             //        Basically once we have NodeList we can throw this out.
 | ||||
|             out() << "    auto* new_array = JS::Array::create(global_object);"; | ||||
|             out() << "    for (auto& element : retval) {"; | ||||
|             out() << "        new_array->indexed_properties().append(wrap(global_object, element));"; | ||||
|             out() << "    }"; | ||||
|             out() << "    return new_array;"; | ||||
|         } else if (return_type.name == "long" || return_type.name == "double") { | ||||
|             out() << "    return JS::Value(retval);"; | ||||
|             scoped_generator.append(R"~~~( | ||||
|     auto* new_array = JS::Array::create(global_object); | ||||
|     for (auto& element : retval) | ||||
|         new_array->indexed_properties().append(wrap(global_object, element)); | ||||
| 
 | ||||
|     return new_array; | ||||
| )~~~"); | ||||
|         } 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") { | ||||
|             out() << "    return retval;"; | ||||
|         } else if (return_type.name == "boolean") { | ||||
|             out() << "    return JS::Value(retval);"; | ||||
|             scoped_generator.append(R"~~~( | ||||
|     return retval; | ||||
| )~~~"); | ||||
|         } 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) { | ||||
|         out() << "JS_DEFINE_NATIVE_GETTER(" << wrapper_class << "::" << attribute.getter_callback_name << ")"; | ||||
|         out() << "{"; | ||||
|         out() << "    auto* impl = impl_from(vm, global_object);"; | ||||
|         out() << "    if (!impl)"; | ||||
|         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();"; | ||||
|         } | ||||
|         auto attribute_generator = generator.fork(); | ||||
|         attribute_generator.set("attribute.getter_callback", attribute.getter_callback_name); | ||||
|         attribute_generator.set("attribute.setter_callback", attribute.setter_callback_name); | ||||
|         attribute_generator.set("attribute.name:snakecase", snake_name(attribute.name)); | ||||
| 
 | ||||
|         if (attribute.extended_attributes.contains("Reflect")) { | ||||
|             auto attribute_name = attribute.extended_attributes.get("Reflect").value(); | ||||
|             if (attribute_name.is_null()) | ||||
|                 attribute_name = 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 { | ||||
|             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); | ||||
|         out() << "}"; | ||||
| 
 | ||||
|         attribute_generator.append(R"~~~( | ||||
| } | ||||
| )~~~"); | ||||
| 
 | ||||
|         if (!attribute.readonly) { | ||||
|             out() << "JS_DEFINE_NATIVE_SETTER(" << wrapper_class << "::" << attribute.setter_callback_name << ")"; | ||||
|             out() << "{"; | ||||
|             out() << "    auto* impl = impl_from(vm, global_object);"; | ||||
|             out() << "    if (!impl)"; | ||||
|             out() << "        return;"; | ||||
|             attribute_generator.append(R"~~~( | ||||
| JS_DEFINE_NATIVE_SETTER(@wrapper_class@::@attribute.setter_callback@) | ||||
| { | ||||
|     auto* impl = impl_from(vm, global_object); | ||||
|     if (!impl) | ||||
|         return; | ||||
| )~~~"); | ||||
| 
 | ||||
|             generate_to_cpp(attribute, "value", "", "cpp_value", true); | ||||
| 
 | ||||
|             if (attribute.extended_attributes.contains("Reflect")) { | ||||
|                 auto attribute_name = attribute.extended_attributes.get("Reflect").value(); | ||||
|                 if (attribute_name.is_null()) | ||||
|                     attribute_name = attribute.name; | ||||
|                 attribute_name = make_input_acceptable_cpp(attribute_name); | ||||
|                 out() << "    impl->set_attribute(HTML::AttributeNames::" << attribute_name << ", cpp_value);"; | ||||
|                 attribute_generator.append(R"~~~( | ||||
|     impl->set_attribute(HTML::AttributeNames::@attribute.reflect_name@, cpp_value); | ||||
| )~~~"); | ||||
|             } 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
 | ||||
|     for (auto& function : interface.functions) { | ||||
|         out() << "JS_DEFINE_NATIVE_FUNCTION(" << wrapper_class << "::" << snake_name(function.name) << ")"; | ||||
|         out() << "{"; | ||||
|         out() << "    auto* impl = impl_from(vm, global_object);"; | ||||
|         out() << "    if (!impl)"; | ||||
|         out() << "        return {};"; | ||||
|         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.nargs", String::number(function.length())); | ||||
| 
 | ||||
|         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) { | ||||
|             out() << "    if (vm.argument_count() < " << function.length() << ") {"; | ||||
|             if (function.length() == 1) | ||||
|                 out() << "        vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountOne, \"" << function.name << "\");"; | ||||
|             else | ||||
|                 out() << "        vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::BadArgCountMany, \"" << function.name << "\", \"" << function.length() << "\");"; | ||||
|             out() << "        return {};"; | ||||
|             out() << "    }"; | ||||
|             if (function.length() == 1) { | ||||
|                 function_generator.set(".bad_arg_count", "JS::ErrorType::BadArgCountOne"); | ||||
|                 function_generator.set(".arg_count_suffix", ""); | ||||
|             } else { | ||||
|                 function_generator.set(".bad_arg_count", "JS::ErrorType::BadArgCountMany"); | ||||
|                 function_generator.set(".arg_count_suffix", String::formatted(", \"{}\"", function.length())); | ||||
|             } | ||||
| 
 | ||||
|             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; | ||||
|         generate_arguments(function.parameters, arguments_builder); | ||||
| 
 | ||||
|         function_generator.set(".arguments", arguments_builder.string_view()); | ||||
| 
 | ||||
|         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 { | ||||
|             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); | ||||
|         out() << "}"; | ||||
|     } | ||||
| 
 | ||||
|     // Implementation: Wrapper factory
 | ||||
|     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() << "}"; | ||||
|     } | ||||
| 
 | ||||
|     out() << "}"; | ||||
|         function_generator.append(R"~~~( | ||||
| } | ||||
| )~~~"); | ||||
|     } | ||||
| 
 | ||||
|     if (should_emit_wrapper_factory(interface)) { | ||||
|         generator.append(R"~~~( | ||||
| @wrapper_class@* wrap(JS::GlobalObject& global_object, @fully_qualified_name@& impl) | ||||
| { | ||||
|     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.parse(argc, argv); | ||||
| 
 | ||||
|     out() << LexicalPath(path).dirname().characters(); | ||||
|     outln("{}", LexicalPath(path).dirname()); | ||||
|     return 0; | ||||
| } | ||||
|  |  | |||
|  | @ -126,7 +126,7 @@ int main(int argc, char** argv) | |||
|         if (current_symbol < symbols.end() && !current_symbol->contains(virtual_offset)) { | ||||
|             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.
 | ||||
|                 out(); | ||||
|                 outln(); | ||||
|                 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) { | ||||
|                 ++current_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)) { | ||||
|                 if (!is_first_symbol && !current_instruction_is_in_symbol) | ||||
|                     out(); | ||||
|                     outln(); | ||||
|                 ++current_symbol; | ||||
|                 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; | ||||
|         } | ||||
| 
 | ||||
|         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()) { | ||||
|             if (list || verbose) | ||||
|                 out() << tar_stream.header().file_name(); | ||||
|                 outln("{}", tar_stream.header().file_name()); | ||||
| 
 | ||||
|             if (extract) { | ||||
|                 Tar::TarFileStream file_stream = tar_stream.file_contents(); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 asynts
						asynts