Преглед на файлове

LibJS: Add name and message properties to NativeError prototypes

Otherwise these will get their name/default message from the Error
prototype, and as a result would always just say "Error" in error
messages, not the specific type.
Something I missed in da177c6, now with tests. :^)
Linus Groh преди 4 години
родител
ревизия
ea60b344eb

+ 9 - 0
Userland/Libraries/LibJS/Runtime/ErrorPrototype.cpp

@@ -90,6 +90,15 @@ JS_DEFINE_NATIVE_FUNCTION(ErrorPrototype::to_string)
     PrototypeName::PrototypeName(GlobalObject& global_object)                            \
         : Object(*global_object.error_prototype())                                       \
     {                                                                                    \
+    }                                                                                    \
+                                                                                         \
+    void PrototypeName::initialize(GlobalObject& global_object)                          \
+    {                                                                                    \
+        auto& vm = this->vm();                                                           \
+        Object::initialize(global_object);                                               \
+        u8 attr = Attribute::Writable | Attribute::Configurable;                         \
+        define_property(vm.names.name, js_string(vm, #ClassName), attr);                 \
+        define_property(vm.names.message, js_string(vm, ""), attr);                      \
     }
 
 JS_ENUMERATE_ERROR_SUBCLASSES

+ 1 - 1
Userland/Libraries/LibJS/Runtime/ErrorPrototype.h

@@ -48,7 +48,7 @@ private:
                                                                                                 \
     public:                                                                                     \
         explicit PrototypeName(GlobalObject&);                                                  \
-        virtual void initialize(GlobalObject&) override { }                                     \
+        virtual void initialize(GlobalObject&) override;                                        \
         virtual ~PrototypeName() override = default;                                            \
     };
 

+ 26 - 0
Userland/Libraries/LibJS/Tests/builtins/Error/Error.prototype.message.js

@@ -0,0 +1,26 @@
+describe("normal behavior", () => {
+    test("initial message value is empty string", () => {
+        expect(Error.prototype.message).toBe("");
+        expect(EvalError.prototype.message).toBe("");
+        expect(RangeError.prototype.message).toBe("");
+        expect(ReferenceError.prototype.message).toBe("");
+        expect(SyntaxError.prototype.message).toBe("");
+        expect(TypeError.prototype.message).toBe("");
+    });
+
+    test("Error gets message via prototype by default", () => {
+        const error = new Error();
+        expect(error.hasOwnProperty("message")).toBeFalse();
+        expect(error.message).toBe("");
+        Error.prototype.message = "Well hello friends";
+        expect(error.message).toBe("Well hello friends");
+    });
+
+    test("Error gets message via object if given to constructor", () => {
+        const error = new Error("Custom error message");
+        expect(error.hasOwnProperty("message")).toBeTrue();
+        expect(error.message).toBe("Custom error message");
+        Error.prototype.message = "Well hello friends";
+        expect(error.message).toBe("Custom error message");
+    });
+});

+ 16 - 8
Userland/Libraries/LibJS/Tests/builtins/Error/Error.prototype.name.js

@@ -1,10 +1,18 @@
-test("basic functionality", () => {
-    expect(Error.prototype).not.toHaveProperty("length");
+describe("normal behavior", () => {
+    test("initial name value is type name", () => {
+        expect(Error.prototype.name).toBe("Error");
+        expect(EvalError.prototype.name).toBe("EvalError");
+        expect(RangeError.prototype.name).toBe("RangeError");
+        expect(ReferenceError.prototype.name).toBe("ReferenceError");
+        expect(SyntaxError.prototype.name).toBe("SyntaxError");
+        expect(TypeError.prototype.name).toBe("TypeError");
+    });
 
-    var changedInstance = new Error("");
-    changedInstance.name = "NewCustomError";
-    expect(changedInstance.name).toBe("NewCustomError");
-
-    var normalInstance = new Error("");
-    expect(normalInstance.name).toBe("Error");
+    test("Error gets name via prototype", () => {
+        const error = new Error();
+        expect(error.hasOwnProperty("name")).toBeFalse();
+        expect(error.name).toBe("Error");
+        Error.prototype.name = "Foo";
+        expect(error.name).toBe("Foo");
+    });
 });