mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-17 16:28:06 +03:00
LibIDL+LibWeb: Add support for static readonly attributes
Support for settable attributes is a FIXME.
This commit is contained in:
parent
7fc4ea5495
commit
316814988f
Notes:
sideshowbarker
2024-07-17 21:16:31 +09:00
Author: https://github.com/Lubrsi Commit: https://github.com/SerenityOS/serenity/commit/316814988f Pull-request: https://github.com/SerenityOS/serenity/pull/23794
@ -3849,6 +3849,20 @@ private:
|
||||
virtual bool has_constructor() const override { return true; }
|
||||
)~~~");
|
||||
|
||||
for (auto& attribute : interface.static_attributes) {
|
||||
auto attribute_generator = generator.fork();
|
||||
attribute_generator.set("attribute.name:snakecase", attribute.name.to_snakecase());
|
||||
attribute_generator.append(R"~~~(
|
||||
JS_DECLARE_NATIVE_FUNCTION(@attribute.name:snakecase@_getter);
|
||||
)~~~");
|
||||
|
||||
if (!attribute.readonly) {
|
||||
attribute_generator.append(R"~~~(
|
||||
JS_DECLARE_NATIVE_FUNCTION(@attribute.name:snakecase@_setter);
|
||||
)~~~");
|
||||
}
|
||||
}
|
||||
|
||||
for (auto const& overload_set : interface.constructor_overload_sets) {
|
||||
auto constructor_generator = generator.fork();
|
||||
if (overload_set.value.size() > 1) {
|
||||
@ -4050,6 +4064,22 @@ void @constructor_class@::initialize(JS::Realm& realm)
|
||||
)~~~");
|
||||
}
|
||||
|
||||
for (auto& attribute : interface.static_attributes) {
|
||||
auto attribute_generator = generator.fork();
|
||||
attribute_generator.set("attribute.name", attribute.name);
|
||||
attribute_generator.set("attribute.getter_callback", attribute.getter_callback_name);
|
||||
attribute_generator.set("attribute.getter_callback", attribute.getter_callback_name);
|
||||
|
||||
if (!attribute.readonly)
|
||||
attribute_generator.set("attribute.setter_callback", attribute.setter_callback_name);
|
||||
else
|
||||
attribute_generator.set("attribute.setter_callback", "nullptr");
|
||||
|
||||
attribute_generator.append(R"~~~(
|
||||
define_native_accessor(realm, "@attribute.name@", @attribute.getter_callback@, @attribute.setter_callback@, default_attributes);
|
||||
)~~~");
|
||||
}
|
||||
|
||||
// https://webidl.spec.whatwg.org/#es-operations
|
||||
for (auto const& overload_set : interface.static_overload_sets) {
|
||||
auto function_generator = generator.fork();
|
||||
@ -4066,6 +4096,35 @@ void @constructor_class@::initialize(JS::Realm& realm)
|
||||
}
|
||||
)~~~");
|
||||
|
||||
// Implementation: Static Attributes
|
||||
for (auto& attribute : interface.static_attributes) {
|
||||
auto attribute_generator = generator.fork();
|
||||
attribute_generator.set("attribute.name", attribute.name);
|
||||
attribute_generator.set("attribute.getter_callback", attribute.getter_callback_name);
|
||||
attribute_generator.set("attribute.setter_callback", attribute.setter_callback_name);
|
||||
|
||||
if (attribute.extended_attributes.contains("ImplementedAs")) {
|
||||
auto implemented_as = attribute.extended_attributes.get("ImplementedAs").value();
|
||||
attribute_generator.set("attribute.cpp_name", implemented_as);
|
||||
} else {
|
||||
attribute_generator.set("attribute.cpp_name", attribute.name.to_snakecase());
|
||||
}
|
||||
|
||||
attribute_generator.append(R"~~~(
|
||||
JS_DEFINE_NATIVE_FUNCTION(@constructor_class@::@attribute.getter_callback@)
|
||||
{
|
||||
auto retval = TRY(throw_dom_exception_if_needed(vm, [&] { return @fully_qualified_name@::@attribute.cpp_name@(vm); }));
|
||||
)~~~");
|
||||
|
||||
generate_return_statement(generator, *attribute.type, interface);
|
||||
|
||||
attribute_generator.append(R"~~~(
|
||||
}
|
||||
)~~~");
|
||||
|
||||
// FIXME: Add support for static attribute setters.
|
||||
}
|
||||
|
||||
// Implementation: Static Functions
|
||||
for (auto& function : interface.static_functions)
|
||||
generate_function(generator, function, StaticFunction::Yes, interface.constructor_class, interface.fully_qualified_name, interface);
|
||||
|
@ -282,7 +282,7 @@ NonnullRefPtr<Type const> Parser::parse_type()
|
||||
return adopt_ref(*new Type(builder.to_byte_string(), nullable));
|
||||
}
|
||||
|
||||
void Parser::parse_attribute(HashMap<ByteString, ByteString>& extended_attributes, Interface& interface)
|
||||
void Parser::parse_attribute(HashMap<ByteString, ByteString>& extended_attributes, Interface& interface, IsStatic is_static)
|
||||
{
|
||||
bool inherit = lexer.consume_specific("inherit"sv);
|
||||
if (inherit)
|
||||
@ -316,7 +316,10 @@ void Parser::parse_attribute(HashMap<ByteString, ByteString>& extended_attribute
|
||||
move(getter_callback_name),
|
||||
move(setter_callback_name),
|
||||
};
|
||||
interface.attributes.append(move(attribute));
|
||||
if (is_static == IsStatic::No)
|
||||
interface.attributes.append(move(attribute));
|
||||
else
|
||||
interface.static_attributes.append(move(attribute));
|
||||
}
|
||||
|
||||
void Parser::parse_constant(Interface& interface)
|
||||
@ -391,14 +394,9 @@ Vector<Parameter> Parser::parse_parameters()
|
||||
return parameters;
|
||||
}
|
||||
|
||||
Function Parser::parse_function(HashMap<ByteString, ByteString>& extended_attributes, Interface& interface, IsSpecialOperation is_special_operation)
|
||||
Function Parser::parse_function(HashMap<ByteString, ByteString>& extended_attributes, Interface& interface, IsStatic is_static, IsSpecialOperation is_special_operation)
|
||||
{
|
||||
auto position = lexer.current_position();
|
||||
bool static_ = false;
|
||||
if (lexer.consume_specific("static"sv)) {
|
||||
static_ = true;
|
||||
consume_whitespace();
|
||||
}
|
||||
|
||||
auto return_type = parse_type();
|
||||
consume_whitespace();
|
||||
@ -414,7 +412,7 @@ Function Parser::parse_function(HashMap<ByteString, ByteString>& extended_attrib
|
||||
|
||||
// "Defining a special operation with an identifier is equivalent to separating the special operation out into its own declaration without an identifier."
|
||||
if (is_special_operation == IsSpecialOperation::No || (is_special_operation == IsSpecialOperation::Yes && !name.is_empty())) {
|
||||
if (!static_)
|
||||
if (is_static == IsStatic::No)
|
||||
interface.functions.append(function);
|
||||
else
|
||||
interface.static_functions.append(function);
|
||||
@ -476,7 +474,7 @@ void Parser::parse_getter(HashMap<ByteString, ByteString>& extended_attributes,
|
||||
{
|
||||
assert_string("getter"sv);
|
||||
consume_whitespace();
|
||||
auto function = parse_function(extended_attributes, interface, IsSpecialOperation::Yes);
|
||||
auto function = parse_function(extended_attributes, interface, IsStatic::No, IsSpecialOperation::Yes);
|
||||
|
||||
if (function.parameters.size() != 1)
|
||||
report_parsing_error(ByteString::formatted("Named/indexed property getters must have only 1 parameter, got {} parameters.", function.parameters.size()), filename, input, lexer.tell());
|
||||
@ -510,7 +508,7 @@ void Parser::parse_setter(HashMap<ByteString, ByteString>& extended_attributes,
|
||||
{
|
||||
assert_string("setter"sv);
|
||||
consume_whitespace();
|
||||
auto function = parse_function(extended_attributes, interface, IsSpecialOperation::Yes);
|
||||
auto function = parse_function(extended_attributes, interface, IsStatic::No, IsSpecialOperation::Yes);
|
||||
|
||||
if (function.parameters.size() != 2)
|
||||
report_parsing_error(ByteString::formatted("Named/indexed property setters must have only 2 parameters, got {} parameter(s).", function.parameters.size()), filename, input, lexer.tell());
|
||||
@ -550,7 +548,7 @@ void Parser::parse_deleter(HashMap<ByteString, ByteString>& extended_attributes,
|
||||
{
|
||||
assert_string("deleter"sv);
|
||||
consume_whitespace();
|
||||
auto function = parse_function(extended_attributes, interface, IsSpecialOperation::Yes);
|
||||
auto function = parse_function(extended_attributes, interface, IsStatic::No, IsSpecialOperation::Yes);
|
||||
|
||||
if (function.parameters.size() != 1)
|
||||
report_parsing_error(ByteString::formatted("Named property deleter must have only 1 parameter, got {} parameters.", function.parameters.size()), filename, input, lexer.tell());
|
||||
@ -647,7 +645,17 @@ void Parser::parse_interface(Interface& interface)
|
||||
continue;
|
||||
}
|
||||
|
||||
parse_function(extended_attributes, interface);
|
||||
bool is_static = lexer.consume_specific("static");
|
||||
if (!is_static) {
|
||||
parse_function(extended_attributes, interface, IsStatic::No);
|
||||
} else {
|
||||
consume_whitespace();
|
||||
if (lexer.next_is("readonly") || lexer.next_is("attribute")) {
|
||||
parse_attribute(extended_attributes, interface, IsStatic::Yes);
|
||||
} else {
|
||||
parse_function(extended_attributes, interface, IsStatic::Yes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (auto legacy_namespace = interface.extended_attributes.get("LegacyNamespace"sv); legacy_namespace.has_value())
|
||||
@ -1081,6 +1089,8 @@ Interface& Parser::parse()
|
||||
// Resolve typedefs
|
||||
for (auto& attribute : interface.attributes)
|
||||
resolve_typedef(interface, attribute.type, &attribute.extended_attributes);
|
||||
for (auto& attribute : interface.static_attributes)
|
||||
resolve_typedef(interface, attribute.type, &attribute.extended_attributes);
|
||||
for (auto& constant : interface.constants)
|
||||
resolve_typedef(interface, constant.type);
|
||||
for (auto& constructor : interface.constructors)
|
||||
|
@ -30,6 +30,11 @@ private:
|
||||
Yes,
|
||||
};
|
||||
|
||||
enum class IsStatic {
|
||||
No,
|
||||
Yes,
|
||||
};
|
||||
|
||||
Parser(Parser* parent, ByteString filename, StringView contents, ByteString import_base_path);
|
||||
|
||||
void assert_specific(char ch);
|
||||
@ -38,7 +43,7 @@ private:
|
||||
Optional<Interface&> resolve_import(auto path);
|
||||
|
||||
HashMap<ByteString, ByteString> parse_extended_attributes();
|
||||
void parse_attribute(HashMap<ByteString, ByteString>& extended_attributes, Interface&);
|
||||
void parse_attribute(HashMap<ByteString, ByteString>& extended_attributes, Interface&, IsStatic is_static = IsStatic::No);
|
||||
void parse_interface(Interface&);
|
||||
void parse_namespace(Interface&);
|
||||
void parse_non_interface_entities(bool allow_interface, Interface&);
|
||||
@ -53,7 +58,7 @@ private:
|
||||
void parse_deleter(HashMap<ByteString, ByteString>& extended_attributes, Interface&);
|
||||
void parse_stringifier(HashMap<ByteString, ByteString>& extended_attributes, Interface&);
|
||||
void parse_iterable(Interface&);
|
||||
Function parse_function(HashMap<ByteString, ByteString>& extended_attributes, Interface&, IsSpecialOperation is_special_operation = IsSpecialOperation::No);
|
||||
Function parse_function(HashMap<ByteString, ByteString>& extended_attributes, Interface&, IsStatic is_static = IsStatic::No, IsSpecialOperation is_special_operation = IsSpecialOperation::No);
|
||||
Vector<Parameter> parse_parameters();
|
||||
NonnullRefPtr<Type const> parse_type();
|
||||
void parse_constant(Interface&);
|
||||
|
@ -270,6 +270,7 @@ public:
|
||||
HashMap<ByteString, ByteString> extended_attributes;
|
||||
|
||||
Vector<Attribute> attributes;
|
||||
Vector<Attribute> static_attributes;
|
||||
Vector<Constant> constants;
|
||||
Vector<Constructor> constructors;
|
||||
Vector<Function> functions;
|
||||
|
Loading…
Reference in New Issue
Block a user