diff options
-rw-r--r-- | Libraries/LibJS/Forward.h | 16 | ||||
-rw-r--r-- | Libraries/LibJS/Interpreter.cpp | 13 | ||||
-rw-r--r-- | Libraries/LibJS/Interpreter.h | 16 | ||||
-rw-r--r-- | Libraries/LibJS/Runtime/Error.cpp | 12 | ||||
-rw-r--r-- | Libraries/LibJS/Runtime/Error.h | 16 | ||||
-rw-r--r-- | Libraries/LibJS/Runtime/ErrorConstructor.cpp | 24 | ||||
-rw-r--r-- | Libraries/LibJS/Runtime/ErrorConstructor.h | 19 | ||||
-rw-r--r-- | Libraries/LibJS/Runtime/ErrorPrototype.cpp | 12 | ||||
-rw-r--r-- | Libraries/LibJS/Runtime/ErrorPrototype.h | 17 | ||||
-rw-r--r-- | Libraries/LibJS/Runtime/GlobalObject.cpp | 5 | ||||
-rw-r--r-- | Libraries/LibJS/Runtime/GlobalObject.h | 14 |
11 files changed, 157 insertions, 7 deletions
diff --git a/Libraries/LibJS/Forward.h b/Libraries/LibJS/Forward.h index c301e3bd0e..130312fd44 100644 --- a/Libraries/LibJS/Forward.h +++ b/Libraries/LibJS/Forward.h @@ -26,6 +26,15 @@ #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) + namespace JS { class ASTNode; @@ -54,6 +63,13 @@ 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 + struct Argument; template<class T> diff --git a/Libraries/LibJS/Interpreter.cpp b/Libraries/LibJS/Interpreter.cpp index 1485fcbf65..b5a40b45f1 100644 --- a/Libraries/LibJS/Interpreter.cpp +++ b/Libraries/LibJS/Interpreter.cpp @@ -57,6 +57,11 @@ Interpreter::Interpreter() 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 } Interpreter::~Interpreter() @@ -178,12 +183,18 @@ void Interpreter::gather_roots(Badge<Heap>, HashTable<Cell*>& roots) roots.set(m_string_prototype); roots.set(m_object_prototype); roots.set(m_array_prototype); - roots.set(m_error_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); if (m_last_value.is_cell()) diff --git a/Libraries/LibJS/Interpreter.h b/Libraries/LibJS/Interpreter.h index b11f2dc94d..7a23cb9dc0 100644 --- a/Libraries/LibJS/Interpreter.h +++ b/Libraries/LibJS/Interpreter.h @@ -139,12 +139,18 @@ public: Object* string_prototype() { return m_string_prototype; } Object* object_prototype() { return m_object_prototype; } Object* array_prototype() { return m_array_prototype; } - Object* error_prototype() { return m_error_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; } void clear_exception() { m_exception = nullptr; } @@ -178,12 +184,18 @@ private: Object* m_string_prototype { nullptr }; Object* m_object_prototype { nullptr }; Object* m_array_prototype { nullptr }; - Object* m_error_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 }; ScopeType m_unwind_until { ScopeType::None }; diff --git a/Libraries/LibJS/Runtime/Error.cpp b/Libraries/LibJS/Runtime/Error.cpp index 029c25d197..417f3735f8 100644 --- a/Libraries/LibJS/Runtime/Error.cpp +++ b/Libraries/LibJS/Runtime/Error.cpp @@ -40,4 +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; } + +JS_ENUMERATE_ERROR_SUBCLASSES +#undef __JS_ENUMERATE_ERROR_SUBCLASS + } diff --git a/Libraries/LibJS/Runtime/Error.h b/Libraries/LibJS/Runtime/Error.h index 411454217e..fc42332baf 100644 --- a/Libraries/LibJS/Runtime/Error.h +++ b/Libraries/LibJS/Runtime/Error.h @@ -24,6 +24,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#pragma once + #include <AK/FlyString.h> #include <LibJS/Runtime/Object.h> @@ -45,4 +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 __JS_ENUMERATE_ERROR_SUBCLASS(TitleCase, snake_case) \ + DECLARE_ERROR_SUBCLASS(TitleCase, snake_case) +JS_ENUMERATE_ERROR_SUBCLASSES +#undef __JS_ENUMERATE_ERROR_SUBCLASS } diff --git a/Libraries/LibJS/Runtime/ErrorConstructor.cpp b/Libraries/LibJS/Runtime/ErrorConstructor.cpp index 9c07c4c2c2..a5a2a625a8 100644 --- a/Libraries/LibJS/Runtime/ErrorConstructor.cpp +++ b/Libraries/LibJS/Runtime/ErrorConstructor.cpp @@ -53,4 +53,28 @@ Value ErrorConstructor::construct(Interpreter& interpreter) return interpreter.heap().allocate<Error>("Error", message); } +#define DEFINE_ERROR_SUBCLASS_CONSTRUCTOR(TitleCase, snake_case) \ + TitleCase##Constructor::TitleCase##Constructor() \ + { \ + put("prototype", interpreter().snake_case##_prototype()); \ + put("length", Value(1)); \ + } \ + TitleCase##Constructor::~TitleCase##Constructor() {} \ + Value TitleCase##Constructor::call(Interpreter& interpreter) \ + { \ + return construct(interpreter); \ + } \ + Value TitleCase##Constructor::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); \ + } + +#define __JS_ENUMERATE_ERROR_SUBCLASS(TitleCase, snake_case) \ + DEFINE_ERROR_SUBCLASS_CONSTRUCTOR(TitleCase, snake_case) +JS_ENUMERATE_ERROR_SUBCLASSES +#undef __JS_ENUMERATE_ERROR_SUBCLASS + } diff --git a/Libraries/LibJS/Runtime/ErrorConstructor.h b/Libraries/LibJS/Runtime/ErrorConstructor.h index 43cc3eb8bb..39c0cdf075 100644 --- a/Libraries/LibJS/Runtime/ErrorConstructor.h +++ b/Libraries/LibJS/Runtime/ErrorConstructor.h @@ -26,6 +26,7 @@ #pragma once +#include <LibJS/Runtime/Error.h> #include <LibJS/Runtime/NativeFunction.h> namespace JS { @@ -43,4 +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 __JS_ENUMERATE_ERROR_SUBCLASS(TitleCase, snake_case) \ + DECLARE_ERROR_SUBCLASS_CONSTRUCTOR(TitleCase, snake_case) +JS_ENUMERATE_ERROR_SUBCLASSES +#undef __JS_ENUMERATE_ERROR_SUBCLASS + } diff --git a/Libraries/LibJS/Runtime/ErrorPrototype.cpp b/Libraries/LibJS/Runtime/ErrorPrototype.cpp index f7be308bce..3e9c923282 100644 --- a/Libraries/LibJS/Runtime/ErrorPrototype.cpp +++ b/Libraries/LibJS/Runtime/ErrorPrototype.cpp @@ -80,7 +80,7 @@ Value ErrorPrototype::to_string(Interpreter& interpreter) auto object_message_property = this_object.get("message"); if (object_message_property.has_value() && !object_message_property.value().is_undefined()) message = object_message_property.value().to_string(); - + if (name.length() == 0) return js_string(interpreter, message); if (message.length() == 0) @@ -88,4 +88,14 @@ 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() {} \ + TitleCase::~TitleCase() {} \ + const char* TitleCase::class_name() const { return #TitleCase; } + +#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 + } diff --git a/Libraries/LibJS/Runtime/ErrorPrototype.h b/Libraries/LibJS/Runtime/ErrorPrototype.h index 58c97c6370..c8ca9f7e85 100644 --- a/Libraries/LibJS/Runtime/ErrorPrototype.h +++ b/Libraries/LibJS/Runtime/ErrorPrototype.h @@ -26,7 +26,7 @@ #pragma once -#include <LibJS/Runtime/Object.h> +#include <LibJS/Runtime/Error.h> namespace JS { @@ -44,4 +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 __JS_ENUMERATE_ERROR_SUBCLASS(TitleCase, snake_case) \ + DECLARE_ERROR_SUBCLASS_PROTOTYPE(TitleCase##Prototype, snake_case##_prototype) +JS_ENUMERATE_ERROR_SUBCLASSES +#undef __JS_ENUMERATE_ERROR_SUBCLASS + } diff --git a/Libraries/LibJS/Runtime/GlobalObject.cpp b/Libraries/LibJS/Runtime/GlobalObject.cpp index 65142ad7a7..fdb97aa982 100644 --- a/Libraries/LibJS/Runtime/GlobalObject.cpp +++ b/Libraries/LibJS/Runtime/GlobalObject.cpp @@ -72,6 +72,11 @@ GlobalObject::GlobalObject() add_constructor("Function", m_function_constructor, *interpreter().function_prototype()); 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()); + JS_ENUMERATE_ERROR_SUBCLASSES +#undef __JS_ENUMERATE_ERROR_SUBCLASS } GlobalObject::~GlobalObject() diff --git a/Libraries/LibJS/Runtime/GlobalObject.h b/Libraries/LibJS/Runtime/GlobalObject.h index 0402a96079..101403003a 100644 --- a/Libraries/LibJS/Runtime/GlobalObject.h +++ b/Libraries/LibJS/Runtime/GlobalObject.h @@ -38,10 +38,15 @@ public: ArrayConstructor* array_constructor() { return m_array_constructor; } BooleanConstructor* boolean_constructor() { return m_boolean_constructor; } DateConstructor* date_constructor() { return m_date_constructor; } - ErrorConstructor* error_constructor() { return m_error_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 protected: virtual void visit_children(Visitor&) override; @@ -58,10 +63,15 @@ private: ArrayConstructor* m_array_constructor { nullptr }; BooleanConstructor* m_boolean_constructor { nullptr }; DateConstructor* m_date_constructor { nullptr }; - ErrorConstructor* m_error_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 }; } |