LibJS+LibWeb: Add JS::Object::inherits(class_name)

To allow implementing the DOM class hierarchy in JS bindings, this
patch adds an inherits() function that can be used to ask an Object
if it inherits from a specific C++ class (by name).

The necessary overrides are baked into each Object subclass by the
new JS_OBJECT macro, which works similarly to C_OBJECT in LibCore.

Thanks to @Dexesttp for suggesting this approach. :^)
This commit is contained in:
Andreas Kling 2020-06-21 15:14:02 +02:00
parent 1914f52371
commit af51dc105a
Notes: sideshowbarker 2024-07-19 05:29:32 +09:00
57 changed files with 122 additions and 106 deletions

View file

@ -31,6 +31,8 @@
namespace JS {
class Array final : public Object {
JS_OBJECT(Array, Object);
public:
static Array* create(GlobalObject&);
@ -40,7 +42,6 @@ public:
static Array* typed_this(Interpreter&, GlobalObject&);
private:
virtual const char* class_name() const override { return "Array"; }
virtual bool is_array() const override { return true; }
JS_DECLARE_NATIVE_GETTER(length_getter);

View file

@ -31,6 +31,8 @@
namespace JS {
class ArrayConstructor final : public NativeFunction {
JS_OBJECT(ArrayConstructor, NativeFunction);
public:
explicit ArrayConstructor(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
@ -41,7 +43,6 @@ public:
private:
virtual bool has_constructor() const override { return true; }
virtual const char* class_name() const override { return "ArrayConstructor"; }
JS_DECLARE_NATIVE_FUNCTION(is_array);
JS_DECLARE_NATIVE_FUNCTION(of);

View file

@ -32,14 +32,14 @@
namespace JS {
class ArrayPrototype final : public Object {
JS_OBJECT(ArrayPrototype, Object);
public:
ArrayPrototype(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~ArrayPrototype() override;
private:
virtual const char* class_name() const override { return "ArrayPrototype"; }
JS_DECLARE_NATIVE_FUNCTION(filter);
JS_DECLARE_NATIVE_FUNCTION(for_each);
JS_DECLARE_NATIVE_FUNCTION(map);

View file

@ -31,6 +31,8 @@
namespace JS {
class BigIntConstructor final : public NativeFunction {
JS_OBJECT(BigIntConstructor, NativeFunction);
public:
explicit BigIntConstructor(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
@ -41,7 +43,6 @@ public:
private:
virtual bool has_constructor() const override { return true; }
virtual const char* class_name() const override { return "BigIntConstructor"; }
JS_DECLARE_NATIVE_FUNCTION(as_int_n);
JS_DECLARE_NATIVE_FUNCTION(as_uint_n);

View file

@ -32,6 +32,8 @@
namespace JS {
class BigIntObject final : public Object {
JS_OBJECT(BigIntObject, Object);
public:
static BigIntObject* create(GlobalObject&, BigInt&);
@ -46,7 +48,6 @@ public:
private:
virtual void visit_children(Visitor&) override;
virtual const char* class_name() const override { return "BigIntObject"; }
virtual bool is_bigint_object() const override { return true; }
BigInt& m_bigint;

View file

@ -31,14 +31,14 @@
namespace JS {
class BigIntPrototype final : public Object {
JS_OBJECT(BigIntPrototype, Object);
public:
explicit BigIntPrototype(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~BigIntPrototype() override;
private:
virtual const char* class_name() const override { return "BigIntPrototype"; }
JS_DECLARE_NATIVE_FUNCTION(to_string);
JS_DECLARE_NATIVE_FUNCTION(to_locale_string);
JS_DECLARE_NATIVE_FUNCTION(value_of);

View file

@ -31,6 +31,8 @@
namespace JS {
class BooleanConstructor final : public NativeFunction {
JS_OBJECT(BooleanConstructor, NativeFunction);
public:
explicit BooleanConstructor(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
@ -41,7 +43,6 @@ public:
private:
virtual bool has_constructor() const override { return true; }
virtual const char* class_name() const override { return "BooleanConstructor"; }
};
}

View file

@ -30,6 +30,8 @@
namespace JS {
class BooleanObject : public Object {
JS_OBJECT(BooleanObject, Object);
public:
static BooleanObject* create(GlobalObject&, bool);
@ -42,7 +44,6 @@ public:
}
private:
virtual const char* class_name() const override { return "BooleanObject"; }
virtual bool is_boolean_object() const override { return true; }
bool m_value { false };
};

View file

@ -31,14 +31,14 @@
namespace JS {
class BooleanPrototype final : public BooleanObject {
JS_OBJECT(BooleanPrototype, BooleanObject);
public:
explicit BooleanPrototype(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~BooleanPrototype() override;
private:
virtual const char* class_name() const override { return "BooleanPrototype"; }
JS_DECLARE_NATIVE_FUNCTION(to_string);
JS_DECLARE_NATIVE_FUNCTION(value_of);
};

View file

@ -31,6 +31,8 @@
namespace JS {
class BoundFunction final : public Function {
JS_OBJECT(BoundFunction, Function);
public:
BoundFunction(GlobalObject&, Function& target_function, Value bound_this, Vector<Value> arguments, i32 length, Object* constructor_prototype);
virtual void initialize(Interpreter&, GlobalObject&) override;
@ -56,7 +58,6 @@ public:
private:
virtual bool is_bound_function() const override { return true; }
virtual const char* class_name() const override { return "BoundFunction"; }
Function* m_target_function = nullptr;
Object* m_constructor_prototype = nullptr;

View file

@ -31,14 +31,14 @@
namespace JS {
class ConsoleObject final : public Object {
JS_OBJECT(ConsoleObject, Object);
public:
explicit ConsoleObject(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~ConsoleObject() override;
private:
virtual const char* class_name() const override { return "ConsoleObject"; }
JS_DECLARE_NATIVE_FUNCTION(log);
JS_DECLARE_NATIVE_FUNCTION(debug);
JS_DECLARE_NATIVE_FUNCTION(info);

View file

@ -32,6 +32,8 @@
namespace JS {
class Date final : public Object {
JS_OBJECT(Date, Object);
public:
static Date* create(GlobalObject&, Core::DateTime, u16 milliseconds);
@ -57,7 +59,6 @@ public:
private:
virtual bool is_date() const final { return true; }
virtual const char* class_name() const override { return "Date"; }
Core::DateTime m_datetime;
u16 m_milliseconds;

View file

@ -31,6 +31,8 @@
namespace JS {
class DateConstructor final : public NativeFunction {
JS_OBJECT(DateConstructor, NativeFunction);
public:
explicit DateConstructor(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
@ -41,7 +43,6 @@ public:
private:
virtual bool has_constructor() const override { return true; }
virtual const char* class_name() const override { return "DateConstructor"; }
JS_DECLARE_NATIVE_FUNCTION(now);
};

View file

@ -31,14 +31,13 @@
namespace JS {
class DatePrototype final : public Object {
JS_OBJECT(DatePrototype, Object);
public:
explicit DatePrototype(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~DatePrototype() override;
private:
virtual const char* class_name() const override { return "DatePrototype"; }
JS_DECLARE_NATIVE_FUNCTION(get_date);
JS_DECLARE_NATIVE_FUNCTION(get_day);
JS_DECLARE_NATIVE_FUNCTION(get_full_year);

View file

@ -57,7 +57,6 @@ Error::~Error()
{ \
} \
ClassName::~ClassName() { } \
const char* ClassName::class_name() const { return #ClassName; }
JS_ENUMERATE_ERROR_SUBCLASSES
#undef __JS_ENUMERATE

View file

@ -32,6 +32,8 @@
namespace JS {
class Error : public Object {
JS_OBJECT(Error, Object);
public:
static Error* create(GlobalObject&, const FlyString& name, const String& message);
@ -45,7 +47,6 @@ public:
private:
virtual bool is_error() const final { return true; }
virtual const char* class_name() const override { return "Error"; }
FlyString m_name;
String m_message;
@ -53,14 +54,13 @@ private:
#define DECLARE_ERROR_SUBCLASS(ClassName, snake_name, PrototypeName, ConstructorName) \
class ClassName final : public Error { \
JS_OBJECT(ClassName, Error); \
\
public: \
static ClassName* create(GlobalObject&, const String& message); \
\
ClassName(const String& message, Object& prototype); \
virtual ~ClassName() override; \
\
private: \
virtual const char* class_name() const override; \
};
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \

View file

@ -32,6 +32,8 @@
namespace JS {
class ErrorConstructor final : public NativeFunction {
JS_OBJECT(ErrorConstructor, NativeFunction);
public:
explicit ErrorConstructor(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
@ -42,11 +44,12 @@ public:
private:
virtual bool has_constructor() const override { return true; }
virtual const char* class_name() const override { return "ErrorConstructor"; }
};
#define DECLARE_ERROR_SUBCLASS_CONSTRUCTOR(ClassName, snake_name, PrototypeName, ConstructorName) \
class ConstructorName final : public NativeFunction { \
JS_OBJECT(ConstructorName, NativeFunction); \
\
public: \
explicit ConstructorName(GlobalObject&); \
virtual void initialize(Interpreter&, GlobalObject&) override; \
@ -56,7 +59,6 @@ private:
\
private: \
virtual bool has_constructor() const override { return true; } \
virtual const char* class_name() const override { return #ClassName "Constructor"; } \
};
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \

View file

@ -126,8 +126,7 @@ JS_DEFINE_NATIVE_FUNCTION(ErrorPrototype::to_string)
: Object(global_object.error_prototype()) \
{ \
} \
PrototypeName::~PrototypeName() { } \
const char* PrototypeName::class_name() const { return #PrototypeName; }
PrototypeName::~PrototypeName() { }
JS_ENUMERATE_ERROR_SUBCLASSES
#undef __JS_ENUMERATE

View file

@ -31,14 +31,14 @@
namespace JS {
class ErrorPrototype final : public Object {
JS_OBJECT(ErrorPrototype, Object);
public:
explicit ErrorPrototype(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~ErrorPrototype() override;
private:
virtual const char* class_name() const override { return "ErrorPrototype"; }
JS_DECLARE_NATIVE_FUNCTION(to_string);
JS_DECLARE_NATIVE_GETTER(name_getter);
@ -49,13 +49,12 @@ private:
#define DECLARE_ERROR_SUBCLASS_PROTOTYPE(ClassName, snake_name, PrototypeName, ConstructorName) \
class PrototypeName final : public Object { \
JS_OBJECT(PrototypeName, Object); \
\
public: \
explicit PrototypeName(GlobalObject&); \
virtual void initialize(Interpreter&, GlobalObject&) override { } \
virtual ~PrototypeName() override; \
\
private: \
virtual const char* class_name() const override; \
};
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \

View file

@ -32,6 +32,8 @@
namespace JS {
class Function : public Object {
JS_OBJECT(Function, Object);
public:
virtual ~Function();
virtual void initialize(Interpreter&, GlobalObject&) override { }
@ -60,7 +62,6 @@ public:
protected:
explicit Function(Object& prototype);
Function(Object& prototype, Value bound_this, Vector<Value> bound_arguments);
virtual const char* class_name() const override { return "Function"; }
private:
virtual bool is_function() const final { return true; }

View file

@ -31,6 +31,8 @@
namespace JS {
class FunctionConstructor final : public NativeFunction {
JS_OBJECT(FunctionConstructor, NativeFunction);
public:
explicit FunctionConstructor(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
@ -41,7 +43,6 @@ public:
private:
virtual bool has_constructor() const override { return true; }
virtual const char* class_name() const override { return "FunctionConstructor"; }
};
}

View file

@ -31,14 +31,14 @@
namespace JS {
class FunctionPrototype final : public Object {
JS_OBJECT(FunctionPrototype, Object);
public:
explicit FunctionPrototype(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~FunctionPrototype() override;
private:
virtual const char* class_name() const override { return "FunctionPrototype"; }
JS_DECLARE_NATIVE_FUNCTION(apply);
JS_DECLARE_NATIVE_FUNCTION(bind);
JS_DECLARE_NATIVE_FUNCTION(call);

View file

@ -32,6 +32,8 @@
namespace JS {
class GlobalObject : public Object {
JS_OBJECT(GlobalObject, Object);
public:
explicit GlobalObject();
virtual void initialize();
@ -53,8 +55,6 @@ protected:
void add_constructor(const FlyString& property_name, ConstructorType*&, Object& prototype);
private:
virtual const char* class_name() const override { return "GlobalObject"; }
JS_DECLARE_NATIVE_FUNCTION(gc);
JS_DECLARE_NATIVE_FUNCTION(is_nan);
JS_DECLARE_NATIVE_FUNCTION(is_finite);

View file

@ -31,6 +31,8 @@
namespace JS {
class JSONObject final : public Object {
JS_OBJECT(JSONObject, Object);
public:
explicit JSONObject(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
@ -45,8 +47,6 @@ private:
Optional<Vector<String>> property_list;
};
virtual const char* class_name() const override { return "JSONObject"; }
// Stringify helpers
static String serialize_json_property(Interpreter&, StringifyState&, const PropertyName& key, Object* holder);
static String serialize_json_object(Interpreter&, StringifyState&, Object&);

View file

@ -31,14 +31,14 @@
namespace JS {
class MathObject final : public Object {
JS_OBJECT(MathObject, Object);
public:
explicit MathObject(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~MathObject() override;
private:
virtual const char* class_name() const override { return "MathObject"; }
JS_DECLARE_NATIVE_FUNCTION(abs);
JS_DECLARE_NATIVE_FUNCTION(random);
JS_DECLARE_NATIVE_FUNCTION(sqrt);

View file

@ -32,6 +32,8 @@
namespace JS {
class NativeFunction : public Function {
JS_OBJECT(NativeFunction, Function);
public:
static NativeFunction* create(Interpreter&, GlobalObject&, const FlyString& name, AK::Function<Value(Interpreter&, GlobalObject&)>);
@ -51,7 +53,6 @@ protected:
private:
virtual bool is_native_function() const override { return true; }
virtual const char* class_name() const override { return "NativeFunction"; }
virtual LexicalEnvironment* create_environment() override final { return nullptr; }
FlyString m_name;

View file

@ -32,6 +32,8 @@
namespace JS {
class NativeProperty final : public Object {
JS_OBJECT(NativeProperty, Object);
public:
NativeProperty(AK::Function<Value(Interpreter&, GlobalObject&)> getter, AK::Function<void(Interpreter&, GlobalObject&, Value)> setter);
virtual ~NativeProperty() override;
@ -41,7 +43,6 @@ public:
private:
virtual bool is_native_property() const override { return true; }
virtual const char* class_name() const override { return "NativeProperty"; }
AK::Function<Value(Interpreter&, GlobalObject&)> m_getter;
AK::Function<void(Interpreter&, GlobalObject&, Value)> m_setter;

View file

@ -31,6 +31,8 @@
namespace JS {
class NumberConstructor final : public NativeFunction {
JS_OBJECT(NumberConstructor, NativeFunction);
public:
explicit NumberConstructor(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
@ -41,7 +43,6 @@ public:
private:
virtual bool has_constructor() const override { return true; }
virtual const char* class_name() const override { return "NumberConstructor"; }
JS_DECLARE_NATIVE_FUNCTION(is_finite);
JS_DECLARE_NATIVE_FUNCTION(is_integer);

View file

@ -31,6 +31,8 @@
namespace JS {
class NumberObject : public Object {
JS_OBJECT(NumberObject, Object);
public:
static NumberObject* create(GlobalObject&, double);
@ -41,8 +43,6 @@ public:
virtual Value value_of() const override { return Value(m_value); }
private:
virtual const char* class_name() const override { return "NumberObject"; }
double m_value { 0 };
};

View file

@ -31,12 +31,11 @@
namespace JS {
class NumberPrototype final : public NumberObject {
JS_OBJECT(NumberPrototype, NumberObject);
public:
explicit NumberPrototype(GlobalObject&);
virtual ~NumberPrototype() override;
private:
virtual const char* class_name() const override { return "NumberPrototype"; }
};
}

View file

@ -39,6 +39,12 @@
namespace JS {
#define JS_OBJECT(class_, base_class) \
public: \
using Base = base_class; \
virtual const char* class_name() const override { return #class_; } \
virtual bool inherits(const StringView& class_name) const override { return class_name == #class_ || Base::inherits(class_name); }
struct PropertyDescriptor {
PropertyAttributes attributes;
Value value;
@ -60,6 +66,8 @@ public:
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~Object();
virtual bool inherits(const StringView& class_name) const { return class_name == this->class_name(); }
enum class GetOwnPropertyMode {
Key,
Value,
@ -111,8 +119,6 @@ public:
virtual bool is_symbol_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 void visit_children(Cell::Visitor&) override;

View file

@ -31,6 +31,8 @@
namespace JS {
class ObjectConstructor final : public NativeFunction {
JS_OBJECT(ObjectConstructor, NativeFunction);
public:
explicit ObjectConstructor(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
@ -41,7 +43,6 @@ public:
private:
virtual bool has_constructor() const override { return true; }
virtual const char* class_name() const override { return "ObjectConstructor"; }
JS_DECLARE_NATIVE_FUNCTION(define_property_);
JS_DECLARE_NATIVE_FUNCTION(is);

View file

@ -31,6 +31,8 @@
namespace JS {
class ObjectPrototype final : public Object {
JS_OBJECT(ObjectPrototype, Object);
public:
explicit ObjectPrototype(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
@ -40,8 +42,6 @@ public:
JS_DECLARE_NATIVE_FUNCTION(to_string);
private:
virtual const char* class_name() const override { return "ObjectPrototype"; }
JS_DECLARE_NATIVE_FUNCTION(has_own_property);
JS_DECLARE_NATIVE_FUNCTION(to_locale_string);
JS_DECLARE_NATIVE_FUNCTION(value_of);

View file

@ -31,6 +31,8 @@
namespace JS {
class ProxyConstructor final : public NativeFunction {
JS_OBJECT(ProxyConstructor, NativeFunction);
public:
explicit ProxyConstructor(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
@ -41,7 +43,6 @@ public:
private:
virtual bool has_constructor() const override { return true; }
virtual const char* class_name() const override { return "ProxyConstructor"; }
};
}

View file

@ -31,6 +31,8 @@
namespace JS {
class ProxyObject : public Object {
JS_OBJECT(ProxyObject, Object);
public:
static ProxyObject* create(GlobalObject&, Object& target, Object& handler);
@ -56,7 +58,6 @@ public:
private:
virtual void visit_children(Visitor&) override;
virtual const char* class_name() const override { return "ProxyObject"; }
virtual bool is_proxy_object() const override { return true; }
virtual bool is_array() const override { return m_target.is_array(); };

View file

@ -31,12 +31,11 @@
namespace JS {
class ProxyPrototype final : public Object {
JS_OBJECT(ProxyPrototype, Object);
public:
explicit ProxyPrototype(GlobalObject&);
virtual ~ProxyPrototype() override;
private:
virtual const char* class_name() const override { return "ProxyPrototype"; }
};
}

View file

@ -31,14 +31,14 @@
namespace JS {
class ReflectObject final : public Object {
JS_OBJECT(ReflectObject, Object);
public:
explicit ReflectObject(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~ReflectObject() override;
private:
virtual const char* class_name() const override { return "ReflectObject"; }
JS_DECLARE_NATIVE_FUNCTION(apply);
JS_DECLARE_NATIVE_FUNCTION(construct);
JS_DECLARE_NATIVE_FUNCTION(define_property);

View file

@ -31,6 +31,8 @@
namespace JS {
class RegExpConstructor final : public NativeFunction {
JS_OBJECT(RegExpConstructor, NativeFunction);
public:
explicit RegExpConstructor(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
@ -41,7 +43,6 @@ public:
private:
virtual bool has_constructor() const override { return true; }
virtual const char* class_name() const override { return "RegExpConstructor"; }
};
}

View file

@ -32,6 +32,8 @@
namespace JS {
class RegExpObject : public Object {
JS_OBJECT(RegExpObject, Object);
public:
static RegExpObject* create(GlobalObject&, String content, String flags);
@ -44,7 +46,6 @@ public:
Value to_string() const override;
private:
virtual const char* class_name() const override { return "RegExpObject"; }
virtual bool is_regexp_object() const override { return true; }
String m_content;

View file

@ -31,12 +31,11 @@
namespace JS {
class RegExpPrototype final : public RegExpObject {
JS_OBJECT(RegExpPrototype, RegExpObject);
public:
explicit RegExpPrototype(GlobalObject&);
virtual ~RegExpPrototype() override;
private:
virtual const char* class_name() const override { return "RegExpPrototype"; }
};
}

View file

@ -32,6 +32,8 @@
namespace JS {
class ScriptFunction final : public Function {
JS_OBJECT(ScriptFunction, Function);
public:
static ScriptFunction* create(GlobalObject&, const FlyString& name, const Statement& body, Vector<FunctionNode::Parameter> parameters, i32 m_function_length, LexicalEnvironment* parent_environment, bool is_arrow_function = false);
@ -50,7 +52,6 @@ public:
private:
virtual bool is_script_function() const override { return true; }
virtual const char* class_name() const override { return "ScriptFunction"; }
virtual LexicalEnvironment* create_environment() override;
virtual void visit_children(Visitor&) override;

View file

@ -31,6 +31,8 @@
namespace JS {
class StringConstructor final : public NativeFunction {
JS_OBJECT(StringConstructor, NativeFunction);
public:
explicit StringConstructor(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
@ -41,7 +43,6 @@ public:
private:
virtual bool has_constructor() const override { return true; }
virtual const char* class_name() const override { return "StringConstructor"; }
JS_DECLARE_NATIVE_FUNCTION(raw);
JS_DECLARE_NATIVE_FUNCTION(from_char_code);

View file

@ -31,6 +31,8 @@
namespace JS {
class StringObject : public Object {
JS_OBJECT(StringObject, Object);
public:
static StringObject* create(GlobalObject&, PrimitiveString&);
@ -45,7 +47,6 @@ public:
private:
virtual void visit_children(Visitor&) override;
virtual const char* class_name() const override { return "StringObject"; }
virtual bool is_string_object() const override { return true; }
PrimitiveString& m_string;

View file

@ -31,14 +31,14 @@
namespace JS {
class StringPrototype final : public StringObject {
JS_OBJECT(StringPrototype, StringObject);
public:
explicit StringPrototype(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~StringPrototype() override;
private:
virtual const char* class_name() const override { return "StringPrototype"; }
JS_DECLARE_NATIVE_FUNCTION(char_at);
JS_DECLARE_NATIVE_FUNCTION(repeat);
JS_DECLARE_NATIVE_FUNCTION(starts_with);

View file

@ -31,6 +31,8 @@
namespace JS {
class SymbolConstructor final : public NativeFunction {
JS_OBJECT(SymbolConstructor, NativeFunction);
public:
explicit SymbolConstructor(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
@ -41,7 +43,6 @@ public:
private:
virtual bool has_constructor() const override { return true; }
virtual const char* class_name() const override { return "SymbolConstructor"; }
JS_DECLARE_NATIVE_FUNCTION(for_);
JS_DECLARE_NATIVE_FUNCTION(key_for);

View file

@ -32,6 +32,8 @@
namespace JS {
class SymbolObject : public Object {
JS_OBJECT(SymbolObject, Object);
public:
static SymbolObject* create(GlobalObject&, Symbol&);
@ -70,7 +72,6 @@ public:
private:
virtual void visit_children(Visitor&) override;
virtual const char* class_name() const override { return "SymbolObject"; }
virtual bool is_symbol_object() const override { return true; }
Symbol& m_symbol;

View file

@ -31,14 +31,14 @@
namespace JS {
class SymbolPrototype final : public Object {
JS_OBJECT(SymbolPrototype, Object);
public:
explicit SymbolPrototype(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~SymbolPrototype() override;
private:
virtual const char* class_name() const override { return "SymbolPrototype"; }
JS_DECLARE_NATIVE_GETTER(description_getter);
JS_DECLARE_NATIVE_FUNCTION(to_string);

View file

@ -31,6 +31,8 @@
namespace JS {
class Uint8ClampedArray final : public Object {
JS_OBJECT(Uint8ClampedArray, Object);
public:
static Uint8ClampedArray* create(GlobalObject&, u32 length);
@ -46,8 +48,6 @@ public:
const u8* data() const { return m_data; }
private:
virtual const char* class_name() const override { return "Uint8ClampedArray"; }
JS_DECLARE_NATIVE_GETTER(length_getter);
u8* m_data { nullptr };

View file

@ -32,6 +32,7 @@ namespace Web {
namespace Bindings {
class CanvasRenderingContext2DWrapper final : public Wrapper {
JS_OBJECT(CanvasRenderingContext2DWrapper, Wrapper);
public:
CanvasRenderingContext2DWrapper(JS::GlobalObject&, CanvasRenderingContext2D&);
virtual void initialize(JS::Interpreter&, JS::GlobalObject&) override;
@ -41,8 +42,6 @@ public:
const CanvasRenderingContext2D& impl() const { return m_impl; }
private:
virtual const char* class_name() const override { return "CanvasRenderingContext2DWrapper"; }
JS_DECLARE_NATIVE_FUNCTION(fill_rect);
JS_DECLARE_NATIVE_FUNCTION(stroke_rect);
JS_DECLARE_NATIVE_FUNCTION(draw_image);

View file

@ -32,6 +32,8 @@ namespace Web {
namespace Bindings {
class EventListenerWrapper final : public Wrapper {
JS_OBJECT(EventListenerWrapper, Wrapper);
public:
EventListenerWrapper(JS::GlobalObject&, EventListener&);
virtual ~EventListenerWrapper() override;
@ -40,8 +42,6 @@ public:
const EventListener& impl() const { return *m_impl; }
private:
virtual const char* class_name() const override { return "EventListenerWrapper"; }
NonnullRefPtr<EventListener> m_impl;
};

View file

@ -32,6 +32,8 @@ namespace Web {
namespace Bindings {
class EventWrapper : public Wrapper {
JS_OBJECT(EventWrapper, Wrapper);
public:
EventWrapper(JS::GlobalObject&, Event&);
virtual ~EventWrapper() override;
@ -40,8 +42,6 @@ public:
const Event& event() const { return m_event; }
private:
virtual const char* class_name() const override { return "EventWrapper"; }
NonnullRefPtr<Event> m_event;
};

View file

@ -32,6 +32,8 @@ namespace Web {
namespace Bindings {
class ImageDataWrapper : public Wrapper {
JS_OBJECT(ImageDataWrapper, Wrapper);
public:
ImageDataWrapper(JS::GlobalObject&, ImageData&);
virtual void initialize(JS::Interpreter&, JS::GlobalObject&) override;
@ -41,8 +43,6 @@ public:
const ImageData& impl() const { return m_impl; }
private:
virtual const char* class_name() const override { return "ImageDataWrapper"; }
JS_DECLARE_NATIVE_GETTER(width_getter);
JS_DECLARE_NATIVE_GETTER(height_getter);
JS_DECLARE_NATIVE_GETTER(data_getter);

View file

@ -33,14 +33,14 @@ namespace Web {
namespace Bindings {
class LocationObject final : public JS::Object {
JS_OBJECT(LocationObject, JS::Object);
public:
explicit LocationObject(JS::GlobalObject&);
virtual void initialize(JS::Interpreter&, JS::GlobalObject&) override;
virtual ~LocationObject() override;
private:
virtual const char* class_name() const override { return "LocationObject"; }
JS_DECLARE_NATIVE_FUNCTION(reload);
JS_DECLARE_NATIVE_GETTER(href_getter);

View file

@ -33,14 +33,14 @@ namespace Web {
namespace Bindings {
class NavigatorObject final : public JS::Object {
JS_OBJECT(NavigatorObject, JS::Object);
public:
NavigatorObject(JS::GlobalObject&);
virtual void initialize(JS::Interpreter&, JS::GlobalObject&) override;
virtual ~NavigatorObject() override;
private:
virtual const char* class_name() const override { return "NavigatorObject"; }
JS_DECLARE_NATIVE_GETTER(user_agent_getter);
};

View file

@ -37,20 +37,14 @@ namespace Bindings {
class Wrapper
: public JS::Object
, public Weakable<Wrapper> {
public:
virtual bool is_event_target_wrapper() const { return false; }
virtual bool is_node_wrapper() const { return false; }
virtual bool is_document_wrapper() const { return false; }
virtual bool is_element_wrapper() const { return false; }
virtual bool is_htmlelement_wrapper() const { return false; }
JS_OBJECT(Wrapper, JS::Object);
public:
protected:
explicit Wrapper(Object& prototype)
: Object(&prototype)
{
}
virtual bool is_web_wrapper() const final { return true; }
};
}

View file

@ -32,14 +32,14 @@ namespace Web {
namespace Bindings {
class XMLHttpRequestPrototype final : public JS::Object {
JS_OBJECT(XMLHttpRequestPrototype, JS::Object);
public:
explicit XMLHttpRequestPrototype(JS::GlobalObject&);
virtual void initialize(JS::Interpreter&, JS::GlobalObject&) override;
virtual ~XMLHttpRequestPrototype() override;
private:
virtual const char* class_name() const override { return "XMLHttpRequestPrototype"; }
JS_DECLARE_NATIVE_FUNCTION(open);
JS_DECLARE_NATIVE_FUNCTION(send);

View file

@ -315,6 +315,7 @@ static void generate_header(const IDL::Interface& interface)
out() << "namespace Bindings {";
out() << "class " << wrapper_class << " : public " << wrapper_base_class << " {";
out() << " JS_OBJECT(" << wrapper_class << ", " << wrapper_base_class << ");";
out() << "public:";
out() << " " << wrapper_class << "(JS::GlobalObject&, " << interface.name << "&);";
out() << " virtual void initialize(JS::Interpreter&, JS::GlobalObject&) override;";
@ -332,7 +333,6 @@ static void generate_header(const IDL::Interface& interface)
out() << " virtual bool " << is_foo_wrapper_name << "() const final { return true; }";
out() << "private:";
out() << " virtual const char* class_name() const override { return \"" << interface.name << "\"; }";
for (auto& function : interface.functions) {
out() << " JS_DECLARE_NATIVE_FUNCTION(" << snake_name(function.name) << ");";
@ -412,8 +412,7 @@ void generate_implementation(const IDL::Interface& interface)
out() << " auto* this_object = interpreter.this_value(global_object).to_object(interpreter, global_object);";
out() << " if (!this_object)";
out() << " return {};";
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() << " if (!this_object->inherits(\"" << wrapper_class << "\")) {";
out() << " interpreter.throw_exception<JS::TypeError>(JS::ErrorType::NotA, \"" << interface.name << "\");";
out() << " return nullptr;";
out() << " }";
@ -441,8 +440,7 @@ void generate_implementation(const IDL::Interface& interface)
out() << " auto " << cpp_name << "_object = " << js_name << js_suffix << ".to_object(interpreter, global_object);";
out() << " if (interpreter.exception())";
generate_return();
auto is_foo_wrapper_name = snake_name(String::format("Is%sWrapper", parameter.type.name.characters()));
out() << " if (!" << cpp_name << "_object->is_web_wrapper() || !static_cast<Wrapper*>(" << cpp_name << "_object)->" << is_foo_wrapper_name << "()) {";
out() << " if (!" << cpp_name << "_object->inherits(\"" << parameter.type.name << "Wrapper\")) {";
out() << " interpreter.throw_exception<JS::TypeError>(JS::ErrorType::NotA, \"" << parameter.type.name << "\");";
generate_return();
out() << " }";