mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 02:57:42 +00:00
LibWeb+LibJS: Add a naive way to check if a wrapper "is" a certain type
Instead of only checking the class_name(), we now generate an is_foo() virtual in the wrapper generator. (It's currently something we override on Bindings::Wrapper, which is not really scalable.) Longer term we'll need to think up something smarter for verifying that one wrapper "is" another type of wrapper.
This commit is contained in:
parent
1ffffa0053
commit
94fdf4fa5a
3 changed files with 19 additions and 4 deletions
|
@ -111,6 +111,8 @@ public:
|
||||||
virtual bool is_symbol_object() const { return false; }
|
virtual bool is_symbol_object() const { return false; }
|
||||||
virtual bool is_bigint_object() const { return false; }
|
virtual bool is_bigint_object() const { return false; }
|
||||||
|
|
||||||
|
virtual bool is_web_wrapper() const { return false; }
|
||||||
|
|
||||||
virtual const char* class_name() const override { return "Object"; }
|
virtual const char* class_name() const override { return "Object"; }
|
||||||
virtual void visit_children(Cell::Visitor&) override;
|
virtual void visit_children(Cell::Visitor&) override;
|
||||||
|
|
||||||
|
|
|
@ -37,11 +37,17 @@ namespace Bindings {
|
||||||
class Wrapper
|
class Wrapper
|
||||||
: public JS::Object
|
: public JS::Object
|
||||||
, public Weakable<Wrapper> {
|
, public Weakable<Wrapper> {
|
||||||
|
public:
|
||||||
|
virtual bool is_node_wrapper() const { return false; }
|
||||||
|
virtual bool is_document_wrapper() const { return false; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
explicit Wrapper(Object& prototype)
|
explicit Wrapper(Object& prototype)
|
||||||
: Object(&prototype)
|
: Object(&prototype)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool is_web_wrapper() const final { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,16 +30,19 @@
|
||||||
#include <LibCore/File.h>
|
#include <LibCore/File.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
static String snake_name(const StringView& camel_name)
|
static String snake_name(const StringView& title_name)
|
||||||
{
|
{
|
||||||
StringBuilder builder;
|
StringBuilder builder;
|
||||||
for (auto ch : camel_name) {
|
bool first = true;
|
||||||
|
for (auto ch : title_name) {
|
||||||
if (isupper(ch)) {
|
if (isupper(ch)) {
|
||||||
builder.append('_');
|
if (!first)
|
||||||
|
builder.append('_');
|
||||||
builder.append(tolower(ch));
|
builder.append(tolower(ch));
|
||||||
} else {
|
} else {
|
||||||
builder.append(ch);
|
builder.append(ch);
|
||||||
}
|
}
|
||||||
|
first = false;
|
||||||
}
|
}
|
||||||
return builder.to_string();
|
return builder.to_string();
|
||||||
}
|
}
|
||||||
|
@ -338,6 +341,9 @@ static void generate_header(const IDL::Interface& interface)
|
||||||
out() << " const " << interface.name << "& impl() const { return static_cast<const " << interface.name << "&>(" << wrapper_base_class << "::impl()); }";
|
out() << " const " << interface.name << "& impl() const { return static_cast<const " << interface.name << "&>(" << wrapper_base_class << "::impl()); }";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto is_foo_wrapper_name = snake_name(String::format("Is%s", wrapper_class.characters()));
|
||||||
|
out() << " virtual bool " << is_foo_wrapper_name << "() const final { return true; }";
|
||||||
|
|
||||||
out() << "private:";
|
out() << "private:";
|
||||||
out() << " virtual const char* class_name() const override { return \"" << interface.name << "\"; }";
|
out() << " virtual const char* class_name() const override { return \"" << interface.name << "\"; }";
|
||||||
|
|
||||||
|
@ -407,7 +413,8 @@ void generate_implementation(const IDL::Interface& interface)
|
||||||
out() << " auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);";
|
out() << " auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);";
|
||||||
out() << " if (!this_object)";
|
out() << " if (!this_object)";
|
||||||
out() << " return {};";
|
out() << " return {};";
|
||||||
out() << " if (StringView(\"" << interface.name << "\") != this_object->class_name()) {";
|
auto is_foo_wrapper_name = snake_name(String::format("Is%s", wrapper_class.characters()));
|
||||||
|
out() << " if (!this_object->is_web_wrapper() || !static_cast<Wrapper*>(this_object)->" << is_foo_wrapper_name << "()) {";
|
||||||
out() << " interpreter.throw_exception<JS::TypeError>(JS::ErrorType::NotA, \"" << interface.name << "\");";
|
out() << " interpreter.throw_exception<JS::TypeError>(JS::ErrorType::NotA, \"" << interface.name << "\");";
|
||||||
out() << " return nullptr;";
|
out() << " return nullptr;";
|
||||||
out() << " }";
|
out() << " }";
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue