|
@@ -1,5 +1,5 @@
|
|
|
/*
|
|
|
- * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
|
|
|
+ * Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
|
|
|
* All rights reserved.
|
|
|
*
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
@@ -136,6 +136,12 @@ struct Function {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+struct Constant {
|
|
|
+ Type type;
|
|
|
+ String name;
|
|
|
+ String value;
|
|
|
+};
|
|
|
+
|
|
|
struct Attribute {
|
|
|
bool readonly { false };
|
|
|
bool unsigned_ { false };
|
|
@@ -153,6 +159,7 @@ struct Interface {
|
|
|
String parent_name;
|
|
|
|
|
|
Vector<Attribute> attributes;
|
|
|
+ Vector<Constant> constants;
|
|
|
Vector<Function> functions;
|
|
|
|
|
|
// Added for convenience after parsing
|
|
@@ -237,6 +244,27 @@ static OwnPtr<Interface> parse_interface(StringView filename, const StringView&
|
|
|
interface->attributes.append(move(attribute));
|
|
|
};
|
|
|
|
|
|
+ auto parse_constant = [&] {
|
|
|
+ lexer.consume_specific("const");
|
|
|
+ consume_whitespace();
|
|
|
+
|
|
|
+ Constant constant;
|
|
|
+ bool unsigned_ = lexer.consume_specific("unsigned");
|
|
|
+ if (unsigned_)
|
|
|
+ consume_whitespace();
|
|
|
+ constant.type = parse_type();
|
|
|
+ consume_whitespace();
|
|
|
+ constant.name = lexer.consume_until([](auto ch) { return isspace(ch) || ch == '='; });
|
|
|
+ consume_whitespace();
|
|
|
+ lexer.consume_specific('=');
|
|
|
+ consume_whitespace();
|
|
|
+ constant.value = lexer.consume_while([](auto ch) { return !isspace(ch) && ch != ';'; });
|
|
|
+ consume_whitespace();
|
|
|
+ assert_specific(';');
|
|
|
+
|
|
|
+ interface->constants.append(move(constant));
|
|
|
+ };
|
|
|
+
|
|
|
auto parse_function = [&](HashMap<String, String>& extended_attributes) {
|
|
|
auto return_type = parse_type();
|
|
|
consume_whitespace();
|
|
@@ -302,6 +330,11 @@ static OwnPtr<Interface> parse_interface(StringView filename, const StringView&
|
|
|
extended_attributes = parse_extended_attributes();
|
|
|
}
|
|
|
|
|
|
+ if (lexer.next_is("const")) {
|
|
|
+ parse_constant();
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
if (lexer.next_is("readonly") || lexer.next_is("attribute")) {
|
|
|
parse_attribute(extended_attributes);
|
|
|
continue;
|
|
@@ -748,6 +781,20 @@ void @constructor_class@::initialize(JS::GlobalObject& global_object)
|
|
|
NativeFunction::initialize(global_object);
|
|
|
define_property(vm.names.prototype, &window.ensure_web_prototype<@prototype_class@>("@name@"), 0);
|
|
|
define_property(vm.names.length, JS::Value(1), JS::Attribute::Configurable);
|
|
|
+
|
|
|
+)~~~");
|
|
|
+
|
|
|
+ for (auto& constant : interface.constants) {
|
|
|
+ auto constant_generator = generator.fork();
|
|
|
+ constant_generator.set("constant.name", constant.name);
|
|
|
+ constant_generator.set("constant.value", constant.value);
|
|
|
+
|
|
|
+ constant_generator.append(R"~~~(
|
|
|
+define_property("@constant.name@", JS::Value((i32)@constant.value@), JS::Attribute::Enumerable);
|
|
|
+)~~~");
|
|
|
+ }
|
|
|
+
|
|
|
+ generator.append(R"~~~(
|
|
|
}
|
|
|
|
|
|
} // namespace Web::Bindings
|
|
@@ -922,6 +969,16 @@ void @prototype_class@::initialize(JS::GlobalObject& global_object)
|
|
|
)~~~");
|
|
|
}
|
|
|
|
|
|
+ for (auto& constant : interface.constants) {
|
|
|
+ auto constant_generator = generator.fork();
|
|
|
+ constant_generator.set("constant.name", constant.name);
|
|
|
+ constant_generator.set("constant.value", constant.value);
|
|
|
+
|
|
|
+ constant_generator.append(R"~~~(
|
|
|
+ define_property("@constant.name@", JS::Value((i32)@constant.value@), JS::Attribute::Enumerable);
|
|
|
+)~~~");
|
|
|
+ }
|
|
|
+
|
|
|
for (auto& function : interface.functions) {
|
|
|
auto function_generator = generator.fork();
|
|
|
function_generator.set("function.name", function.name);
|
|
@@ -1093,9 +1150,13 @@ static @fully_qualified_name@* impl_from(JS::VM& vm, JS::GlobalObject& global_ob
|
|
|
|
|
|
return new_array;
|
|
|
)~~~");
|
|
|
- } else if (return_type.name == "long" || return_type.name == "double" || return_type.name == "boolean" || return_type.name == "short") {
|
|
|
+ } else if (return_type.name == "boolean" || return_type.name == "double" || return_type.name == "long") {
|
|
|
scoped_generator.append(R"~~~(
|
|
|
return JS::Value(retval);
|
|
|
+)~~~");
|
|
|
+ } else if (return_type.name == "short") {
|
|
|
+ scoped_generator.append(R"~~~(
|
|
|
+ return JS::Value((i32)retval);
|
|
|
)~~~");
|
|
|
} else if (return_type.name == "Uint8ClampedArray") {
|
|
|
scoped_generator.append(R"~~~(
|