Browse Source

LibJS: Implement Error.prototype.name setter (#1776)

The MDN example for creating a custom error type in javascript uses:

    function CustomError(foo, message, fileName, lineNumber) {
        var instance = new Error(message, fileName, lineNumber);
        instance.name = 'CustomError';
        instance.foo = foo;
        Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
        return instance;
    }

The name property on the Error prototype needs to be settable for
this to work properly.
Brian Gianforcaro 5 years ago
parent
commit
2a65db7c12

+ 2 - 0
Libraries/LibJS/Runtime/Error.h

@@ -39,6 +39,8 @@ public:
     const FlyString& name() const { return m_name; }
     const String& message() const { return m_message; }
 
+    void set_name(const FlyString& name) { m_name = name; }
+
 private:
     virtual bool is_error() const final { return true; }
     virtual const char* class_name() const override { return "Error"; }

+ 14 - 1
Libraries/LibJS/Runtime/ErrorPrototype.cpp

@@ -36,7 +36,7 @@ namespace JS {
 
 ErrorPrototype::ErrorPrototype()
 {
-    put_native_property("name", name_getter, nullptr);
+    put_native_property("name", name_getter, name_setter);
     put_native_property("message", message_getter, nullptr);
     put_native_function("toString", to_string);
 }
@@ -55,6 +55,19 @@ Value ErrorPrototype::name_getter(Interpreter& interpreter)
     return js_string(interpreter, static_cast<const Error*>(this_object)->name());
 }
 
+void ErrorPrototype::name_setter(Interpreter& interpreter, Value value)
+{
+    auto* this_object = interpreter.this_value().to_object(interpreter.heap());
+    if (!this_object)
+        return;
+    if (!this_object->is_error()) {
+        interpreter.throw_exception<TypeError>("Not an Error object");
+        return;
+    }
+    auto name = FlyString(value.to_string());
+    static_cast<Error*>(this_object)->set_name(name);
+}
+
 Value ErrorPrototype::message_getter(Interpreter& interpreter)
 {
     auto* this_object = interpreter.this_value().to_object(interpreter.heap());

+ 2 - 0
Libraries/LibJS/Runtime/ErrorPrototype.h

@@ -41,6 +41,8 @@ private:
     static Value to_string(Interpreter&);
 
     static Value name_getter(Interpreter&);
+    static void name_setter(Interpreter&, Value);
+
     static Value message_getter(Interpreter&);
 };
 

+ 12 - 0
Libraries/LibJS/Tests/Error.prototype.name.js

@@ -0,0 +1,12 @@
+try {
+    var changedInstance = new Error("");
+    changedInstance.name = 'NewCustomError';
+    assert(changedInstance.name === "NewCustomError");
+
+    var normalInstance = new Error("");
+    assert(normalInstance.name === "Error");
+
+    console.log("PASS");
+} catch (e) {
+    console.log("FAIL: " + e.message);
+}