Browse Source

LibWeb: Allow JS wrappers to customize get() and put()

You can now set the CustomGet and/or CustomPut extended attributes on
an interface. This allows you to override JS::Object::get/put in the
wrapper class.
Andreas Kling 4 years ago
parent
commit
ab23ef92b6
1 changed files with 35 additions and 19 deletions
  1. 35 19
      Userland/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp

+ 35 - 19
Userland/Libraries/LibWeb/CodeGenerators/WrapperGenerator.cpp

@@ -148,6 +148,8 @@ struct Interface {
     String name;
     String parent_name;
 
+    HashMap<String, String> extended_attributes;
+
     Vector<Attribute> attributes;
     Vector<Constant> constants;
     Vector<Constructor> constructors;
@@ -190,6 +192,28 @@ static OwnPtr<Interface> parse_interface(StringView filename, const StringView&
             report_parsing_error(String::formatted("expected '{}'", expected), filename, input, lexer.tell());
     };
 
+    auto parse_extended_attributes = [&] {
+        HashMap<String, String> extended_attributes;
+        for (;;) {
+            consume_whitespace();
+            if (lexer.consume_specific(']'))
+                break;
+            auto name = lexer.consume_until([](auto ch) { return ch == ']' || ch == '=' || ch == ','; });
+            if (lexer.consume_specific('=')) {
+                auto value = lexer.consume_until([](auto ch) { return ch == ']' || ch == ','; });
+                extended_attributes.set(name, value);
+            } else {
+                extended_attributes.set(name, {});
+            }
+            lexer.consume_specific(',');
+        }
+        consume_whitespace();
+        return extended_attributes;
+    };
+
+    if (lexer.consume_specific('['))
+        interface->extended_attributes = parse_extended_attributes();
+
     assert_string("interface");
     consume_whitespace();
     interface->name = lexer.consume_until([](auto ch) { return isspace(ch); });
@@ -303,25 +327,6 @@ static OwnPtr<Interface> parse_interface(StringView filename, const StringView&
         interface->constructors.append(Constructor { interface->name, move(parameters) });
     };
 
-    auto parse_extended_attributes = [&] {
-        HashMap<String, String> extended_attributes;
-        for (;;) {
-            consume_whitespace();
-            if (lexer.consume_specific(']'))
-                break;
-            auto name = lexer.consume_until([](auto ch) { return ch == ']' || ch == '=' || ch == ','; });
-            if (lexer.consume_specific('=')) {
-                auto value = lexer.consume_until([](auto ch) { return ch == ']' || ch == ','; });
-                extended_attributes.set(name, value);
-            } else {
-                extended_attributes.set(name, {});
-            }
-            lexer.consume_specific(',');
-        }
-        consume_whitespace();
-        return extended_attributes;
-    };
-
     for (;;) {
         HashMap<String, String> extended_attributes;
 
@@ -691,6 +696,17 @@ public:
     virtual ~@wrapper_class@() override;
 )~~~");
 
+    if (interface.extended_attributes.contains("CustomGet")) {
+        generator.append(R"~~~(
+    virtual JS::Value get(const JS::PropertyName&, JS::Value receiver = {}) const override;
+)~~~");
+    }
+    if (interface.extended_attributes.contains("CustomPut")) {
+        generator.append(R"~~~(
+    virtual bool put(const JS::PropertyName&, JS::Value, JS::Value receiver = {}) override;
+)~~~");
+    }
+
     if (interface.wrapper_base_class == "Wrapper") {
         generator.append(R"~~~(
     @fully_qualified_name@& impl() { return *m_impl; }