mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-19 09:17:38 +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; }
|
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) {
|
for (auto const& overload_set : interface.constructor_overload_sets) {
|
||||||
auto constructor_generator = generator.fork();
|
auto constructor_generator = generator.fork();
|
||||||
if (overload_set.value.size() > 1) {
|
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
|
// https://webidl.spec.whatwg.org/#es-operations
|
||||||
for (auto const& overload_set : interface.static_overload_sets) {
|
for (auto const& overload_set : interface.static_overload_sets) {
|
||||||
auto function_generator = generator.fork();
|
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
|
// Implementation: Static Functions
|
||||||
for (auto& function : interface.static_functions)
|
for (auto& function : interface.static_functions)
|
||||||
generate_function(generator, function, StaticFunction::Yes, interface.constructor_class, interface.fully_qualified_name, interface);
|
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));
|
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);
|
bool inherit = lexer.consume_specific("inherit"sv);
|
||||||
if (inherit)
|
if (inherit)
|
||||||
@ -316,7 +316,10 @@ void Parser::parse_attribute(HashMap<ByteString, ByteString>& extended_attribute
|
|||||||
move(getter_callback_name),
|
move(getter_callback_name),
|
||||||
move(setter_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)
|
void Parser::parse_constant(Interface& interface)
|
||||||
@ -391,14 +394,9 @@ Vector<Parameter> Parser::parse_parameters()
|
|||||||
return 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();
|
auto position = lexer.current_position();
|
||||||
bool static_ = false;
|
|
||||||
if (lexer.consume_specific("static"sv)) {
|
|
||||||
static_ = true;
|
|
||||||
consume_whitespace();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto return_type = parse_type();
|
auto return_type = parse_type();
|
||||||
consume_whitespace();
|
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."
|
// "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 (is_special_operation == IsSpecialOperation::No || (is_special_operation == IsSpecialOperation::Yes && !name.is_empty())) {
|
||||||
if (!static_)
|
if (is_static == IsStatic::No)
|
||||||
interface.functions.append(function);
|
interface.functions.append(function);
|
||||||
else
|
else
|
||||||
interface.static_functions.append(function);
|
interface.static_functions.append(function);
|
||||||
@ -476,7 +474,7 @@ void Parser::parse_getter(HashMap<ByteString, ByteString>& extended_attributes,
|
|||||||
{
|
{
|
||||||
assert_string("getter"sv);
|
assert_string("getter"sv);
|
||||||
consume_whitespace();
|
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)
|
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());
|
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);
|
assert_string("setter"sv);
|
||||||
consume_whitespace();
|
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)
|
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());
|
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);
|
assert_string("deleter"sv);
|
||||||
consume_whitespace();
|
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)
|
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());
|
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;
|
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())
|
if (auto legacy_namespace = interface.extended_attributes.get("LegacyNamespace"sv); legacy_namespace.has_value())
|
||||||
@ -1081,6 +1089,8 @@ Interface& Parser::parse()
|
|||||||
// Resolve typedefs
|
// Resolve typedefs
|
||||||
for (auto& attribute : interface.attributes)
|
for (auto& attribute : interface.attributes)
|
||||||
resolve_typedef(interface, attribute.type, &attribute.extended_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)
|
for (auto& constant : interface.constants)
|
||||||
resolve_typedef(interface, constant.type);
|
resolve_typedef(interface, constant.type);
|
||||||
for (auto& constructor : interface.constructors)
|
for (auto& constructor : interface.constructors)
|
||||||
|
@ -30,6 +30,11 @@ private:
|
|||||||
Yes,
|
Yes,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class IsStatic {
|
||||||
|
No,
|
||||||
|
Yes,
|
||||||
|
};
|
||||||
|
|
||||||
Parser(Parser* parent, ByteString filename, StringView contents, ByteString import_base_path);
|
Parser(Parser* parent, ByteString filename, StringView contents, ByteString import_base_path);
|
||||||
|
|
||||||
void assert_specific(char ch);
|
void assert_specific(char ch);
|
||||||
@ -38,7 +43,7 @@ private:
|
|||||||
Optional<Interface&> resolve_import(auto path);
|
Optional<Interface&> resolve_import(auto path);
|
||||||
|
|
||||||
HashMap<ByteString, ByteString> parse_extended_attributes();
|
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_interface(Interface&);
|
||||||
void parse_namespace(Interface&);
|
void parse_namespace(Interface&);
|
||||||
void parse_non_interface_entities(bool allow_interface, 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_deleter(HashMap<ByteString, ByteString>& extended_attributes, Interface&);
|
||||||
void parse_stringifier(HashMap<ByteString, ByteString>& extended_attributes, Interface&);
|
void parse_stringifier(HashMap<ByteString, ByteString>& extended_attributes, Interface&);
|
||||||
void parse_iterable(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();
|
Vector<Parameter> parse_parameters();
|
||||||
NonnullRefPtr<Type const> parse_type();
|
NonnullRefPtr<Type const> parse_type();
|
||||||
void parse_constant(Interface&);
|
void parse_constant(Interface&);
|
||||||
|
@ -270,6 +270,7 @@ public:
|
|||||||
HashMap<ByteString, ByteString> extended_attributes;
|
HashMap<ByteString, ByteString> extended_attributes;
|
||||||
|
|
||||||
Vector<Attribute> attributes;
|
Vector<Attribute> attributes;
|
||||||
|
Vector<Attribute> static_attributes;
|
||||||
Vector<Constant> constants;
|
Vector<Constant> constants;
|
||||||
Vector<Constructor> constructors;
|
Vector<Constructor> constructors;
|
||||||
Vector<Function> functions;
|
Vector<Function> functions;
|
||||||
|
Loading…
Reference in New Issue
Block a user