Result of Error.prototype.toString not ES5 conformant
authorbarraclough@apple.com <barraclough@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 15 Nov 2011 20:34:59 +0000 (20:34 +0000)
committerbarraclough@apple.com <barraclough@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 15 Nov 2011 20:34:59 +0000 (20:34 +0000)
https://bugs.webkit.org/show_bug.cgi?id=70889

Reviewed by Oliver Hunt.

Source/JavaScriptCore:

* runtime/ErrorPrototype.cpp:
(JSC::errorProtoFuncToString):

LayoutTests:

* fast/js/native-error-prototype-expected.txt:
* fast/js/script-tests/native-error-prototype.js:
* fast/js/script-tests/toString-recursion.js:
* fast/js/toString-recursion-expected.txt:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@100310 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/js/native-error-prototype-expected.txt
LayoutTests/fast/js/script-tests/native-error-prototype.js
LayoutTests/fast/js/script-tests/toString-recursion.js
LayoutTests/fast/js/toString-recursion-expected.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/runtime/ErrorPrototype.cpp

index d285d3501117523f504142f5218fd3e0052b100c..24689a31786b59774611166c4e02ab3c965841a0 100644 (file)
@@ -1,3 +1,15 @@
+2011-11-15  Gavin Barraclough  <barraclough@apple.com>
+
+        Result of Error.prototype.toString not ES5 conformant
+        https://bugs.webkit.org/show_bug.cgi?id=70889
+
+        Reviewed by Oliver Hunt.
+
+        * fast/js/native-error-prototype-expected.txt:
+        * fast/js/script-tests/native-error-prototype.js:
+        * fast/js/script-tests/toString-recursion.js:
+        * fast/js/toString-recursion-expected.txt:
+
 2011-11-15  Eugene Nalimov  <enal@google.com>
 
         Event listener for active DOM object that is also DOM node can be garbage collected prematurely.
index 71761bfab80291032050de866e2c2b71015531cc..97d45a80536a1cebc19aceab039f94c35556cd98 100644 (file)
@@ -1,10 +1,11 @@
-This is a test case for bug 55346.
+This is a test case for bug 55346 and bug 70889.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
 PASS ({}).toString.call(Error.prototype) is "[object Error]"
 PASS ({}).toString.call(RangeError.prototype) is "[object Error]"
+PASS err.toString() is "message"
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 5acac258f64ef96ee0f0edb2739d610d097af434..fb004765358389c6d5a87178adc2dfe7d70e4b6b 100644 (file)
@@ -1,6 +1,10 @@
 description(
-'This is a test case for <a href="https://bugs.webkit.org/show_bug.cgi?id=55346">bug 55346</a>.'
+'This is a test case for <a href="https://bugs.webkit.org/show_bug.cgi?id=55346">bug 55346</a> and <a href="https://bugs.webkit.org/show_bug.cgi?id=70889">bug 70889</a>.'
 );
 
 shouldBe("({}).toString.call(Error.prototype)", '"[object Error]"');
 shouldBe("({}).toString.call(RangeError.prototype)", '"[object Error]"');
+
+var err = new Error("message");
+err.name = "";
+shouldBe("err.toString()", '"message"');
index d9836b8ff90207ba1b2e8377180d6c7acf2be09b..d71be2b3908f187665acb32afc5b9aed084608b3 100644 (file)
@@ -6,7 +6,7 @@ description(
 shouldBe("var array = []; array[0] = array; array + ''", "''");
 
 // Error (name, message)
-shouldBe("var error = new Error; error.name = error; error.message = error; error + ''", "''");
+shouldBe("var error = new Error; error.name = error; error.message = error; error + ''", "''");
 
 // RegExp (source)
 shouldBe("var regexp = /a/; regexp.source = regexp; regexp + ''", "'/a/'");
index 8a00e9ae0fd3c133ad8deb8762d819df6e737838..8b109f6f8c71313eb9398cddaac31dd0b459edbf 100644 (file)
@@ -4,7 +4,7 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 
 
 PASS var array = []; array[0] = array; array + '' is ''
-PASS var error = new Error; error.name = error; error.message = error; error + '' is ''
+PASS var error = new Error; error.name = error; error.message = error; error + '' is ''
 PASS var regexp = /a/; regexp.source = regexp; regexp + '' is '/a/'
 PASS successfullyParsed is true
 
index 855f081d891d52e496bfbb05931483fd6417b59a..33dd38835b89b2c1cd136e7904a183e28337a0ae 100644 (file)
@@ -1,3 +1,13 @@
+2011-11-15  Gavin Barraclough  <barraclough@apple.com>
+
+        Result of Error.prototype.toString not ES5 conformant
+        https://bugs.webkit.org/show_bug.cgi?id=70889
+
+        Reviewed by Oliver Hunt.
+
+        * runtime/ErrorPrototype.cpp:
+        (JSC::errorProtoFuncToString):
+
 2011-11-15  Simon Hausmann  <simon.hausmann@nokia.com>
 
         [Qt] Centralize hide_symbols and ensure all libs are built with symbol visibility & bsymbolic_functions
index 904dc3cd59c8e0c076df01410cb5fb03e3604fa5..e1a395c0e224509f65291899e5d7589927af8b17 100644 (file)
@@ -21,6 +21,7 @@
 #include "config.h"
 #include "ErrorPrototype.h"
 
+#include "Error.h"
 #include "JSFunction.h"
 #include "JSString.h"
 #include "JSStringBuilder.h"
@@ -74,27 +75,64 @@ bool ErrorPrototype::getOwnPropertyDescriptor(JSObject* object, ExecState* exec,
 
 // ------------------------------ Functions ---------------------------
 
+// ECMA-262 5.1, 15.11.4.4
 EncodedJSValue JSC_HOST_CALL errorProtoFuncToString(ExecState* exec)
 {
-    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+    // 1. Let O be the this value.
+    JSValue thisValue = exec->hostThisValue();
 
+    // 2. If Type(O) is not Object, throw a TypeError exception.
+    if (!thisValue.isObject())
+        return throwVMTypeError(exec);
+    JSObject* thisObj = asObject(thisValue);
+
+    // Guard against recursion!
     StringRecursionChecker checker(exec, thisObj);
     if (JSValue earlyReturnValue = checker.earlyReturnValue())
         return JSValue::encode(earlyReturnValue);
 
+    // 3. Let name be the result of calling the [[Get]] internal method of O with argument "name".
     JSValue name = thisObj->get(exec, exec->propertyNames().name);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
+
+    // 4. If name is undefined, then let name be "Error"; else let name be ToString(name).
+    UString nameString;
+    if (name.isUndefined())
+        nameString = "Error";
+    else {
+        nameString = name.toString(exec);
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
+    }
+
+    // 5. Let msg be the result of calling the [[Get]] internal method of O with argument "message".
     JSValue message = thisObj->get(exec, exec->propertyNames().message);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
+
+    // (sic)
+    // 6. If msg is undefined, then let msg be the empty String; else let msg be ToString(msg).
+    // 7. If msg is undefined, then let msg be the empty String; else let msg be ToString(msg).
+    UString messageString;
+    if (message.isUndefined())
+        messageString = "";
+    else {
+        messageString = message.toString(exec);
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
+    }
 
-    // Mozilla-compatible format.
+    // 8. If name is the empty String, return msg.
+    if (!nameString.length())
+        return JSValue::encode(message.isString() ? message : jsString(exec, messageString));
 
-    if (!name.isUndefined()) {
-        if (!message.isUndefined())
-            return JSValue::encode(jsMakeNontrivialString(exec, name.toString(exec), ": ", message.toString(exec)));
-        return JSValue::encode(jsNontrivialString(exec, name.toString(exec)));
-    }
-    if (!message.isUndefined())
-        return JSValue::encode(jsMakeNontrivialString(exec, "Error: ", message.toString(exec)));
-    return JSValue::encode(jsNontrivialString(exec, "Error"));
+    // 9. If msg is the empty String, return name.
+    if (!messageString.length())
+        return JSValue::encode(name.isString() ? name : jsNontrivialString(exec, nameString));
+
+    // 10. Return the result of concatenating name, ":", a single space character, and msg.
+    return JSValue::encode(jsMakeNontrivialString(exec, nameString, ": ", messageString));
 }
 
 } // namespace JSC