Przeglądaj źródła

LibJS: Use enumerator macros for boilerplate code around native types

Andreas Kling 5 lat temu
rodzic
commit
cb0dfd8f72

+ 28 - 23
Libraries/LibJS/Forward.h

@@ -26,36 +26,41 @@
 
 #pragma once
 
-#define JS_ENUMERATE_ERROR_SUBCLASSES                              \
-    __JS_ENUMERATE_ERROR_SUBCLASS(EvalError, eval_error)           \
-    __JS_ENUMERATE_ERROR_SUBCLASS(InternalError, internal_error)   \
-    __JS_ENUMERATE_ERROR_SUBCLASS(RangeError, range_error)         \
-    __JS_ENUMERATE_ERROR_SUBCLASS(ReferenceError, reference_error) \
-    __JS_ENUMERATE_ERROR_SUBCLASS(SyntaxError, syntax_error)       \
-    __JS_ENUMERATE_ERROR_SUBCLASS(TypeError, type_error)           \
-    __JS_ENUMERATE_ERROR_SUBCLASS(URIError, uri_error)
+#define JS_ENUMERATE_NATIVE_OBJECTS                                              \
+    __JS_ENUMERATE(Array, array, ArrayPrototype, ArrayConstructor)               \
+    __JS_ENUMERATE(BooleanObject, boolean, BooleanPrototype, BooleanConstructor) \
+    __JS_ENUMERATE(Date, date, DatePrototype, DateConstructor)                   \
+    __JS_ENUMERATE(Error, error, ErrorPrototype, ErrorConstructor)               \
+    __JS_ENUMERATE(Function, function, FunctionPrototype, FunctionConstructor)   \
+    __JS_ENUMERATE(NumberObject, number, NumberPrototype, NumberConstructor)     \
+    __JS_ENUMERATE(Object, object, ObjectPrototype, ObjectConstructor)           \
+    __JS_ENUMERATE(StringObject, string, StringPrototype, StringConstructor)
+
+#define JS_ENUMERATE_ERROR_SUBCLASSES                                                                   \
+    __JS_ENUMERATE(EvalError, eval_error, EvalErrorPrototype, EvalErrorConstructor)                     \
+    __JS_ENUMERATE(InternalError, internal_error, InternalErrorPrototype, InternalErrorConstructor)     \
+    __JS_ENUMERATE(RangeError, range_error, RangeErrorPrototype, RangeErrorConstructor)                 \
+    __JS_ENUMERATE(ReferenceError, reference_error, ReferenceErrorPrototype, ReferenceErrorConstructor) \
+    __JS_ENUMERATE(SyntaxError, syntax_error, SyntaxErrorPrototype, SyntaxErrorConstructor)             \
+    __JS_ENUMERATE(TypeError, type_error, TypeErrorPrototype, TypeErrorConstructor)                     \
+    __JS_ENUMERATE(URIError, uri_error, URIErrorPrototype, URIErrorConstructor)
+
+#define JS_ENUMERATE_BUILTIN_TYPES \
+    JS_ENUMERATE_NATIVE_OBJECTS    \
+    JS_ENUMERATE_ERROR_SUBCLASSES
 
 namespace JS {
 
 class ASTNode;
-class ArrayConstructor;
-class BooleanConstructor;
 class Cell;
-class DateConstructor;
 class Error;
-class ErrorConstructor;
 class Exception;
 class Expression;
-class Function;
-class FunctionConstructor;
 class GlobalObject;
 class HandleImpl;
 class Heap;
 class HeapBlock;
 class Interpreter;
-class NumberConstructor;
-class Object;
-class ObjectConstructor;
 class PrimitiveString;
 class ScopeNode;
 class Shape;
@@ -63,12 +68,12 @@ class Statement;
 class Value;
 enum class DeclarationKind;
 
-#define __JS_ENUMERATE_ERROR_SUBCLASS(TitleCase, snake_case) \
-    class TitleCase;                                         \
-    class TitleCase##Constructor;                            \
-    class TitleCase##Prototype;
-JS_ENUMERATE_ERROR_SUBCLASSES
-#undef __JS_ENUMERATE_ERROR_SUBCLASS
+#define __JS_ENUMERATE(ClassName, snake_name, ConstructorName, PrototypeName) \
+    class ClassName;                                                          \
+    class ConstructorName;                                                    \
+    class PrototypeName;
+JS_ENUMERATE_BUILTIN_TYPES
+#undef __JS_ENUMERATE
 
 struct Argument;
 

+ 12 - 27
Libraries/LibJS/Interpreter.cpp

@@ -49,19 +49,15 @@ Interpreter::Interpreter()
 {
     m_empty_object_shape = heap().allocate<Shape>();
 
+    // These are done first since other prototypes depend on their presence.
     m_object_prototype = heap().allocate<ObjectPrototype>();
     m_function_prototype = heap().allocate<FunctionPrototype>();
-    m_string_prototype = heap().allocate<StringPrototype>();
-    m_array_prototype = heap().allocate<ArrayPrototype>();
-    m_error_prototype = heap().allocate<ErrorPrototype>();
-    m_date_prototype = heap().allocate<DatePrototype>();
-    m_number_prototype = heap().allocate<NumberPrototype>();
-    m_boolean_prototype = heap().allocate<BooleanPrototype>();
-
-#define __JS_ENUMERATE_ERROR_SUBCLASS(TitleCase, snake_case) \
-    m_##snake_case##_prototype = heap().allocate<TitleCase##Prototype>();
-    JS_ENUMERATE_ERROR_SUBCLASSES
-#undef __JS_ENUMERATE_ERROR_SUBCLASS
+
+#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
+    if (!m_##snake_name##_prototype)                                          \
+        m_##snake_name##_prototype = heap().allocate<PrototypeName>();
+    JS_ENUMERATE_BUILTIN_TYPES
+#undef __JS_ENUMERATE
 }
 
 Interpreter::~Interpreter()
@@ -178,25 +174,14 @@ Optional<Value> Interpreter::get_variable(const FlyString& name)
 void Interpreter::gather_roots(Badge<Heap>, HashTable<Cell*>& roots)
 {
     roots.set(m_empty_object_shape);
-
     roots.set(m_global_object);
-    roots.set(m_string_prototype);
-    roots.set(m_object_prototype);
-    roots.set(m_array_prototype);
-    roots.set(m_date_prototype);
-    roots.set(m_function_prototype);
-    roots.set(m_number_prototype);
-    roots.set(m_boolean_prototype);
-
-    roots.set(m_error_prototype);
-
-#define __JS_ENUMERATE_ERROR_SUBCLASS(TitleCase, snake_case) \
-    roots.set(m_##snake_case##_prototype);
-    JS_ENUMERATE_ERROR_SUBCLASSES
-#undef __JS_ENUMERATE_ERROR_SUBCLASS
-
     roots.set(m_exception);
 
+#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
+    roots.set(m_##snake_name##_prototype);
+    JS_ENUMERATE_BUILTIN_TYPES
+#undef __JS_ENUMERATE
+
     if (m_last_value.is_cell())
         roots.set(m_last_value.as_cell());
 

+ 14 - 30
Libraries/LibJS/Interpreter.h

@@ -136,22 +136,15 @@ public:
 
     Shape* empty_object_shape() { return m_empty_object_shape; }
 
-    Object* string_prototype() { return m_string_prototype; }
-    Object* object_prototype() { return m_object_prototype; }
-    Object* array_prototype() { return m_array_prototype; }
-    Object* date_prototype() { return m_date_prototype; }
-    Object* function_prototype() { return m_function_prototype; }
-    Object* number_prototype() { return m_number_prototype; }
-    Object* boolean_prototype() { return m_boolean_prototype; }
-
-    Object* error_prototype() { return m_error_prototype; }
-
-#define __JS_ENUMERATE_ERROR_SUBCLASS(TitleCase, snake_case) \
-    Object* snake_case##_prototype() { return m_##snake_case##_prototype; }
-    JS_ENUMERATE_ERROR_SUBCLASSES
-#undef __JS_ENUMERATE_ERROR_SUBCLASS
-
-    Exception* exception() { return m_exception; }
+#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
+    Object* snake_name##_prototype() { return m_##snake_name##_prototype; }
+    JS_ENUMERATE_BUILTIN_TYPES
+#undef __JS_ENUMERATE
+
+    Exception* exception()
+    {
+        return m_exception;
+    }
     void clear_exception() { m_exception = nullptr; }
 
     template<typename T, typename... Args>
@@ -180,21 +173,12 @@ private:
 
     Shape* m_empty_object_shape { nullptr };
 
+#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
+    Object* m_##snake_name##_prototype { nullptr };
+    JS_ENUMERATE_BUILTIN_TYPES
+#undef __JS_ENUMERATE
+
     Object* m_global_object { nullptr };
-    Object* m_string_prototype { nullptr };
-    Object* m_object_prototype { nullptr };
-    Object* m_array_prototype { nullptr };
-    Object* m_date_prototype { nullptr };
-    Object* m_function_prototype { nullptr };
-    Object* m_number_prototype { nullptr };
-    Object* m_boolean_prototype { nullptr };
-
-    Object* m_error_prototype { nullptr };
-
-#define __JS_ENUMERATE_ERROR_SUBCLASS(TitleCase, snake_case) \
-    Object* m_##snake_case##_prototype;
-    JS_ENUMERATE_ERROR_SUBCLASSES
-#undef __JS_ENUMERATE_ERROR_SUBCLASS
 
     Exception* m_exception { nullptr };
 

+ 9 - 9
Libraries/LibJS/Runtime/Error.cpp

@@ -40,16 +40,16 @@ Error::~Error()
 {
 }
 
-#define __JS_ENUMERATE_ERROR_SUBCLASS(TitleCase, snake_case)      \
-    TitleCase::TitleCase(const String& message)                \
-        : Error(#TitleCase, message)                           \
-    {                                                          \
-        set_prototype(interpreter().snake_case##_prototype()); \
-    }                                                          \
-    TitleCase::~TitleCase() {}                                 \
-    const char* TitleCase::class_name() const { return #TitleCase; }
+#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
+    ClassName::ClassName(const String& message)                               \
+        : Error(#ClassName, message)                                          \
+    {                                                                         \
+        set_prototype(interpreter().snake_name##_prototype());                \
+    }                                                                         \
+    ClassName::~ClassName() {}                                                \
+    const char* ClassName::class_name() const { return #ClassName; }
 
 JS_ENUMERATE_ERROR_SUBCLASSES
-#undef __JS_ENUMERATE_ERROR_SUBCLASS
+#undef __JS_ENUMERATE
 
 }

+ 11 - 11
Libraries/LibJS/Runtime/Error.h

@@ -47,18 +47,18 @@ private:
     String m_message;
 };
 
-#define DECLARE_ERROR_SUBCLASS(TitleCase, snake_case)    \
-    class TitleCase final : public Error {               \
-    public:                                              \
-        TitleCase(const String& message);                \
-        virtual ~TitleCase() override;                   \
-                                                         \
-    private:                                             \
-        virtual const char* class_name() const override; \
+#define DECLARE_ERROR_SUBCLASS(ClassName, snake_name, PrototypeName, ConstructorName) \
+    class ClassName final : public Error {                                            \
+    public:                                                                           \
+        ClassName(const String& message);                                             \
+        virtual ~ClassName() override;                                                \
+                                                                                      \
+    private:                                                                          \
+        virtual const char* class_name() const override;                              \
     };
 
-#define __JS_ENUMERATE_ERROR_SUBCLASS(TitleCase, snake_case) \
-    DECLARE_ERROR_SUBCLASS(TitleCase, snake_case)
+#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
+    DECLARE_ERROR_SUBCLASS(ClassName, snake_name, PrototypeName, ConstructorName)
 JS_ENUMERATE_ERROR_SUBCLASSES
-#undef __JS_ENUMERATE_ERROR_SUBCLASS
+#undef __JS_ENUMERATE
 }

+ 8 - 10
Libraries/LibJS/Runtime/ErrorConstructor.cpp

@@ -53,28 +53,26 @@ Value ErrorConstructor::construct(Interpreter& interpreter)
     return interpreter.heap().allocate<Error>("Error", message);
 }
 
-#define DEFINE_ERROR_SUBCLASS_CONSTRUCTOR(TitleCase, snake_case)                                                     \
-    TitleCase##Constructor::TitleCase##Constructor()                                                                 \
+#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName)                                        \
+    ConstructorName::ConstructorName()                                                                               \
     {                                                                                                                \
-        put("prototype", interpreter().snake_case##_prototype());                                                    \
+        put("prototype", interpreter().snake_name##_prototype());                                                    \
         put("length", Value(1));                                                                                     \
     }                                                                                                                \
-    TitleCase##Constructor::~TitleCase##Constructor() {}                                                             \
-    Value TitleCase##Constructor::call(Interpreter& interpreter)                                                     \
+    ConstructorName::~ConstructorName() {}                                                                           \
+    Value ConstructorName::call(Interpreter& interpreter)                                                            \
     {                                                                                                                \
         return construct(interpreter);                                                                               \
     }                                                                                                                \
-    Value TitleCase##Constructor::construct(Interpreter& interpreter)                                                \
+    Value ConstructorName::construct(Interpreter& interpreter)                                                       \
     {                                                                                                                \
         String message = "";                                                                                         \
         if (!interpreter.call_frame().arguments.is_empty() && !interpreter.call_frame().arguments[0].is_undefined()) \
             message = interpreter.call_frame().arguments[0].to_string();                                             \
-        return interpreter.heap().allocate<TitleCase>(message);                                                      \
+        return interpreter.heap().allocate<ClassName>(message);                                                      \
     }
 
-#define __JS_ENUMERATE_ERROR_SUBCLASS(TitleCase, snake_case) \
-    DEFINE_ERROR_SUBCLASS_CONSTRUCTOR(TitleCase, snake_case)
 JS_ENUMERATE_ERROR_SUBCLASSES
-#undef __JS_ENUMERATE_ERROR_SUBCLASS
+#undef __JS_ENUMERATE
 
 }

+ 14 - 14
Libraries/LibJS/Runtime/ErrorConstructor.h

@@ -44,22 +44,22 @@ private:
     virtual const char* class_name() const override { return "ErrorConstructor"; }
 };
 
-#define DECLARE_ERROR_SUBCLASS_CONSTRUCTOR(TitleCase, snake_case)                            \
-    class TitleCase##Constructor final : public NativeFunction {                             \
-    public:                                                                                  \
-        TitleCase##Constructor();                                                            \
-        virtual ~TitleCase##Constructor() override;                                          \
-        virtual Value call(Interpreter&) override;                                           \
-        virtual Value construct(Interpreter&) override;                                      \
-                                                                                             \
-    private:                                                                                 \
-        virtual bool has_constructor() const override { return true; }                       \
-        virtual const char* class_name() const override { return #TitleCase "Constructor"; } \
+#define DECLARE_ERROR_SUBCLASS_CONSTRUCTOR(ClassName, snake_name, PrototypeName, ConstructorName) \
+    class ConstructorName final : public NativeFunction {                                         \
+    public:                                                                                       \
+        ConstructorName();                                                                        \
+        virtual ~ConstructorName() override;                                                      \
+        virtual Value call(Interpreter&) override;                                                \
+        virtual Value construct(Interpreter&) override;                                           \
+                                                                                                  \
+    private:                                                                                      \
+        virtual bool has_constructor() const override { return true; }                            \
+        virtual const char* class_name() const override { return #ClassName "Constructor"; }      \
     };
 
-#define __JS_ENUMERATE_ERROR_SUBCLASS(TitleCase, snake_case) \
-    DECLARE_ERROR_SUBCLASS_CONSTRUCTOR(TitleCase, snake_case)
+#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
+    DECLARE_ERROR_SUBCLASS_CONSTRUCTOR(ClassName, snake_name, PrototypeName, ConstructorName)
 JS_ENUMERATE_ERROR_SUBCLASSES
-#undef __JS_ENUMERATE_ERROR_SUBCLASS
+#undef __JS_ENUMERATE
 
 }

+ 8 - 10
Libraries/LibJS/Runtime/ErrorPrototype.cpp

@@ -88,17 +88,15 @@ Value ErrorPrototype::to_string(Interpreter& interpreter)
     return js_string(interpreter, String::format("%s: %s", name.characters(), message.characters()));
 }
 
-#define DEFINE_ERROR_SUBCLASS_PROTOTYPE(TitleCase, snake_case) \
-    TitleCase::TitleCase()                                     \
-    {                                                          \
-        set_prototype(interpreter().error_prototype());        \
-    }                                                          \
-    TitleCase::~TitleCase() {}                                 \
-    const char* TitleCase::class_name() const { return #TitleCase; }
+#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
+    PrototypeName::PrototypeName()                                            \
+    {                                                                         \
+        set_prototype(interpreter().error_prototype());                       \
+    }                                                                         \
+    PrototypeName::~PrototypeName() {}                                        \
+    const char* PrototypeName::class_name() const { return #PrototypeName; }
 
-#define __JS_ENUMERATE_ERROR_SUBCLASS(TitleCase, snake_case) \
-    DEFINE_ERROR_SUBCLASS_PROTOTYPE(TitleCase##Prototype, snake_case##_prototype)
 JS_ENUMERATE_ERROR_SUBCLASSES
-#undef __JS_ENUMERATE_ERROR_SUBCLASS
+#undef __JS_ENUMERATE
 
 }

+ 11 - 11
Libraries/LibJS/Runtime/ErrorPrototype.h

@@ -44,19 +44,19 @@ private:
     static Value message_getter(Interpreter&);
 };
 
-#define DECLARE_ERROR_SUBCLASS_PROTOTYPE(TitleCase, snake_case) \
-    class TitleCase final : public Object {                     \
-    public:                                                     \
-        TitleCase();                                            \
-        virtual ~TitleCase() override;                          \
-                                                                \
-    private:                                                    \
-        virtual const char* class_name() const override;        \
+#define DECLARE_ERROR_SUBCLASS_PROTOTYPE(ClassName, snake_name, PrototypeName, ConstructorName) \
+    class PrototypeName final : public Object {                                                 \
+    public:                                                                                     \
+        PrototypeName();                                                                        \
+        virtual ~PrototypeName() override;                                                      \
+                                                                                                \
+    private:                                                                                    \
+        virtual const char* class_name() const override;                                        \
     };
 
-#define __JS_ENUMERATE_ERROR_SUBCLASS(TitleCase, snake_case) \
-    DECLARE_ERROR_SUBCLASS_PROTOTYPE(TitleCase##Prototype, snake_case##_prototype)
+#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
+    DECLARE_ERROR_SUBCLASS_PROTOTYPE(ClassName, snake_name, PrototypeName, ConstructorName)
 JS_ENUMERATE_ERROR_SUBCLASSES
-#undef __JS_ENUMERATE_ERROR_SUBCLASS
+#undef __JS_ENUMERATE
 
 }

+ 3 - 3
Libraries/LibJS/Runtime/GlobalObject.cpp

@@ -73,10 +73,10 @@ GlobalObject::GlobalObject()
     add_constructor("Number", m_number_constructor, *interpreter().number_prototype());
     add_constructor("Object", m_object_constructor, *interpreter().object_prototype());
 
-#define __JS_ENUMERATE_ERROR_SUBCLASS(TitleCase, snake_case) \
-    add_constructor(#TitleCase, m_##snake_case##_constructor, *interpreter().snake_case##_prototype());
+#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
+    add_constructor(#ClassName, m_##snake_name##_constructor, *interpreter().snake_name##_prototype());
     JS_ENUMERATE_ERROR_SUBCLASSES
-#undef __JS_ENUMERATE_ERROR_SUBCLASS
+#undef __JS_ENUMERATE
 }
 
 GlobalObject::~GlobalObject()

+ 8 - 24
Libraries/LibJS/Runtime/GlobalObject.h

@@ -35,18 +35,10 @@ public:
     explicit GlobalObject();
     virtual ~GlobalObject() override;
 
-    ArrayConstructor* array_constructor() { return m_array_constructor; }
-    BooleanConstructor* boolean_constructor() { return m_boolean_constructor; }
-    DateConstructor* date_constructor() { return m_date_constructor; }
-    FunctionConstructor* function_constructor() { return m_function_constructor; }
-    NumberConstructor* number_constructor() { return m_number_constructor; };
-    ObjectConstructor* object_constructor() { return m_object_constructor; }
-    ErrorConstructor* error_constructor() { return m_error_constructor; }
-
-#define __JS_ENUMERATE_ERROR_SUBCLASS(TitleCase, snake_case) \
-    TitleCase##Constructor* snake_case##_constructor() { return m_##snake_case##_constructor; }
-    JS_ENUMERATE_ERROR_SUBCLASSES
-#undef __JS_ENUMERATE_ERROR_SUBCLASS
+#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
+    ConstructorName* snake_name##_constructor() { return m_##snake_name##_constructor; }
+    JS_ENUMERATE_BUILTIN_TYPES
+#undef __JS_ENUMERATE
 
 protected:
     virtual void visit_children(Visitor&) override;
@@ -60,18 +52,10 @@ private:
     template<typename ConstructorType>
     void add_constructor(const FlyString& property_name, ConstructorType*&, Object& prototype);
 
-    ArrayConstructor* m_array_constructor { nullptr };
-    BooleanConstructor* m_boolean_constructor { nullptr };
-    DateConstructor* m_date_constructor { nullptr };
-    FunctionConstructor* m_function_constructor { nullptr };
-    NumberConstructor* m_number_constructor { nullptr };
-    ObjectConstructor* m_object_constructor { nullptr };
-    ErrorConstructor* m_error_constructor { nullptr };
-
-#define __JS_ENUMERATE_ERROR_SUBCLASS(TitleCase, snake_case) \
-    TitleCase##Constructor* m_##snake_case##_constructor;
-    JS_ENUMERATE_ERROR_SUBCLASSES
-#undef __JS_ENUMERATE_ERROR_SUBCLASS
+#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
+    ConstructorName* m_##snake_name##_constructor { nullptr };
+    JS_ENUMERATE_BUILTIN_TYPES
+#undef __JS_ENUMERATE
 };
 
 }