From af119d92cb86bba404d48d8ca08b8e22f1a3dd8f Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Wed, 15 Mar 2023 14:40:51 -0400 Subject: [PATCH] LibIDL+LibWeb: Begin supporting the LegacyNamespace extended attribute This is used by WebAssembly IDL files. For now, we mostly use this for error messages and cache keys (to ensure compatibility with existing code as WebAssembly is ported to IDL). --- .../LibWeb/BindingsGenerator/IDLGenerators.cpp | 14 ++++++++------ .../LibWeb/GenerateWindowOrWorkerInterfaces.cpp | 4 ++-- Userland/Libraries/LibIDL/IDLParser.cpp | 5 +++++ Userland/Libraries/LibIDL/Types.h | 1 + 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp index 206d0d7adc..8e7efbbd77 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp @@ -2279,6 +2279,7 @@ static void generate_prototype_or_global_mixin_definitions(IDL::Interface const& auto is_global_interface = interface.extended_attributes.contains("Global"); auto class_name = is_global_interface ? interface.global_mixin_class : interface.prototype_class; generator.set("name", interface.name); + generator.set("namespaced_name", interface.namespaced_name); generator.set("class_name", class_name); generator.set("fully_qualified_name", interface.fully_qualified_name); @@ -2421,7 +2422,7 @@ JS::ThrowCompletionOr @class_name@::initialize(JS::Realm& realm) } generator.append(R"~~~( - define_direct_property(*vm.well_known_symbol_to_string_tag(), MUST_OR_THROW_OOM(JS::PrimitiveString::create(vm, "@name@"sv)), JS::Attribute::Configurable); + define_direct_property(*vm.well_known_symbol_to_string_tag(), MUST_OR_THROW_OOM(JS::PrimitiveString::create(vm, "@namespaced_name@"sv)), JS::Attribute::Configurable); )~~~"); if (!is_global_interface) { @@ -2460,7 +2461,7 @@ static JS::ThrowCompletionOr<@fully_qualified_name@*> impl_from(JS::VM& vm) generator.append(R"~~~( if (!is<@fully_qualified_name@>(this_object)) - return vm.throw_completion(JS::ErrorType::NotAnObjectOfType, "@name@"); + return vm.throw_completion(JS::ErrorType::NotAnObjectOfType, "@namespaced_name@"); return static_cast<@fully_qualified_name@*>(this_object); } )~~~"); @@ -2560,7 +2561,7 @@ JS_DEFINE_NATIVE_FUNCTION(@class_name@::@attribute.setter_callback@) { auto this_value = vm.this_value(); if (!this_value.is_object() || !is<@fully_qualified_name@>(this_value.as_object())) - return vm.throw_completion(JS::ErrorType::NotAnObjectOfType, "@name@"); + return vm.throw_completion(JS::ErrorType::NotAnObjectOfType, "@namespaced_name@"); TRY(this_value.as_object().internal_define_own_property("@attribute.name@", JS::PropertyDescriptor { .value = vm.argument(0), .writable = true })); return JS::js_undefined(); } @@ -2877,6 +2878,7 @@ void generate_constructor_implementation(IDL::Interface const& interface, String SourceGenerator generator { builder }; generator.set("name", interface.name); + generator.set("namespaced_name", interface.namespaced_name); generator.set("prototype_class", interface.prototype_class); generator.set("constructor_class", interface.constructor_class); generator.set("fully_qualified_name", interface.fully_qualified_name); @@ -2973,7 +2975,7 @@ namespace Web::Bindings { JS::ThrowCompletionOr @constructor_class@::call() { - return vm().throw_completion(JS::ErrorType::ConstructorWithoutNew, "@name@"); + return vm().throw_completion(JS::ErrorType::ConstructorWithoutNew, "@namespaced_name@"); } JS::ThrowCompletionOr> @constructor_class@::construct(FunctionObject&) @@ -2984,7 +2986,7 @@ JS::ThrowCompletionOr> @constructor_class@::constru // No constructor generator.set("constructor.length", "0"); generator.append(R"~~~( - return vm().throw_completion(JS::ErrorType::NotAConstructor, "@name@"); + return vm().throw_completion(JS::ErrorType::NotAConstructor, "@namespaced_name@"); )~~~"); } else if (interface.constructors.size() == 1) { // Single constructor @@ -3029,7 +3031,7 @@ JS::ThrowCompletionOr @constructor_class@::initialize(JS::Realm& realm) [[maybe_unused]] u8 default_attributes = JS::Attribute::Enumerable; MUST_OR_THROW_OOM(Base::initialize(realm)); - define_direct_property(vm.names.prototype, &ensure_web_prototype<@prototype_class@>(realm, "@name@"), 0); + define_direct_property(vm.names.prototype, &ensure_web_prototype<@prototype_class@>(realm, "@namespaced_name@"), 0); define_direct_property(vm.names.length, JS::Value(@constructor.length@), JS::Attribute::Configurable); )~~~"); diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWindowOrWorkerInterfaces.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWindowOrWorkerInterfaces.cpp index 8c44a6a92f..0b9b6fa7a4 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWindowOrWorkerInterfaces.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWindowOrWorkerInterfaces.cpp @@ -225,7 +225,7 @@ void Intrinsics::create_web_prototype_and_constructor<@prototype_class@>(JS::Rea if (interface.is_namespace) add_namespace(gen, interface.name, interface.namespace_class); else - add_interface(gen, interface.name, interface.prototype_class, interface.constructor_class, lookup_legacy_constructor(interface)); + add_interface(gen, interface.namespaced_name, interface.prototype_class, interface.constructor_class, lookup_legacy_constructor(interface)); } // FIXME: Special case WebAssembly. We should convert WASM to use IDL. @@ -346,7 +346,7 @@ void add_@global_object_snake_name@_exposed_interfaces(JS::Object& global) if (interface.is_namespace) add_namespace(gen, interface.name, interface.namespace_class); else - add_interface(gen, interface.name, interface.prototype_class, lookup_legacy_constructor(interface)); + add_interface(gen, interface.namespaced_name, interface.prototype_class, lookup_legacy_constructor(interface)); } generator.append(R"~~~( diff --git a/Userland/Libraries/LibIDL/IDLParser.cpp b/Userland/Libraries/LibIDL/IDLParser.cpp index 0e3683fcb9..0470c87fdb 100644 --- a/Userland/Libraries/LibIDL/IDLParser.cpp +++ b/Userland/Libraries/LibIDL/IDLParser.cpp @@ -592,6 +592,11 @@ void Parser::parse_interface(Interface& interface) parse_function(extended_attributes, interface); } + if (auto legacy_namespace = interface.extended_attributes.get("LegacyNamespace"sv); legacy_namespace.has_value()) + interface.namespaced_name = DeprecatedString::formatted("{}.{}", *legacy_namespace, interface.name); + else + interface.namespaced_name = interface.name; + interface.constructor_class = DeprecatedString::formatted("{}Constructor", interface.name); interface.prototype_class = DeprecatedString::formatted("{}Prototype", interface.name); interface.prototype_base_class = DeprecatedString::formatted("{}Prototype", interface.parent_name.is_empty() ? "Object" : interface.parent_name); diff --git a/Userland/Libraries/LibIDL/Types.h b/Userland/Libraries/LibIDL/Types.h index dab0884e47..a471fb0aca 100644 --- a/Userland/Libraries/LibIDL/Types.h +++ b/Userland/Libraries/LibIDL/Types.h @@ -255,6 +255,7 @@ public: DeprecatedString name; DeprecatedString parent_name; + DeprecatedString namespaced_name; bool is_namespace { false }; bool is_mixin { false };