summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Libraries/LibJS/Forward.h16
-rw-r--r--Libraries/LibJS/Interpreter.cpp13
-rw-r--r--Libraries/LibJS/Interpreter.h16
-rw-r--r--Libraries/LibJS/Runtime/Error.cpp12
-rw-r--r--Libraries/LibJS/Runtime/Error.h16
-rw-r--r--Libraries/LibJS/Runtime/ErrorConstructor.cpp24
-rw-r--r--Libraries/LibJS/Runtime/ErrorConstructor.h19
-rw-r--r--Libraries/LibJS/Runtime/ErrorPrototype.cpp12
-rw-r--r--Libraries/LibJS/Runtime/ErrorPrototype.h17
-rw-r--r--Libraries/LibJS/Runtime/GlobalObject.cpp5
-rw-r--r--Libraries/LibJS/Runtime/GlobalObject.h14
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
};
}