Bug 635010 - new Error(undefined).hasOwnProperty("message") should be false. r=jorendorff.
authorTom Schuster <evilpies@gmail.com>
Tue, 08 Mar 2011 16:15:30 -0600
changeset 64249 2a7515434a1dab9d77cf338a30b3f17a85978de7
parent 64248 cb7853aa2d3ab5be7d981495e28b712985b61e9c
child 64250 320432649bc7f512986f26fbb6f51d604e80b072
push idunknown
push userunknown
push dateunknown
reviewersjorendorff
bugs635010
milestone2.0b13pre
Bug 635010 - new Error(undefined).hasOwnProperty("message") should be false. r=jorendorff.
js/src/jsexn.cpp
js/src/tests/ecma_5/misc/error-undefined-message.js
js/src/tests/ecma_5/misc/jstests.list
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -468,16 +468,25 @@ exn_resolve(JSContext *cx, JSObject *obj
     *objp = NULL;
     priv = GetExnPrivate(cx, obj);
     if (priv && JSID_IS_ATOM(id)) {
         str = JSID_TO_STRING(id);
 
         atom = cx->runtime->atomState.messageAtom;
         if (str == ATOM_TO_STRING(atom)) {
             prop = js_message_str;
+
+            /*
+             * Per ES5 15.11.1.1, if Error is called with no argument or with
+             * undefined as the argument, it returns an Error object with no
+             * own message property.
+             */
+            if (!priv->message)
+                return true;
+
             v = STRING_TO_JSVAL(priv->message);
             goto define;
         }
 
         atom = cx->runtime->atomState.fileNameAtom;
         if (str == ATOM_TO_STRING(atom)) {
             prop = js_fileName_str;
             v = STRING_TO_JSVAL(priv->filename);
@@ -490,32 +499,32 @@ exn_resolve(JSContext *cx, JSObject *obj
             v = INT_TO_JSVAL(priv->lineno);
             goto define;
         }
 
         atom = cx->runtime->atomState.stackAtom;
         if (str == ATOM_TO_STRING(atom)) {
             stack = StackTraceToString(cx, priv);
             if (!stack)
-                return JS_FALSE;
+                return false;
 
             /* Allow to GC all things that were used to build stack trace. */
             priv->stackDepth = 0;
             prop = js_stack_str;
             v = STRING_TO_JSVAL(stack);
             goto define;
         }
     }
-    return JS_TRUE;
+    return true;
 
   define:
     if (!JS_DefineProperty(cx, obj, prop, v, NULL, NULL, JSPROP_ENUMERATE))
-        return JS_FALSE;
+        return false;
     *objp = obj;
-    return JS_TRUE;
+    return true;
 }
 
 JSErrorReport *
 js_ErrorFromException(JSContext *cx, jsval exn)
 {
     JSObject *obj;
     JSExnPrivate *priv;
 
@@ -730,23 +739,23 @@ Exception(JSContext *cx, uintN argc, Val
      * If it's a new object of class Exception, then null out the private
      * data so that the finalizer doesn't attempt to free it.
      */
     if (obj->getClass() == &js_ErrorClass)
         obj->setPrivate(NULL);
 
     /* Set the 'message' property. */
     Value *argv = vp + 2;
-    if (argc != 0) {
+    if (argc != 0 && !argv[0].isUndefined()) {
         message = js_ValueToString(cx, argv[0]);
         if (!message)
             return JS_FALSE;
         argv[0].setString(message);
     } else {
-        message = cx->runtime->emptyString;
+        message = NULL;
     }
 
     /* Set the 'fileName' property. */
     if (argc > 1) {
         filename = js_ValueToString(cx, argv[1]);
         if (!filename)
             return JS_FALSE;
         argv[1].setString(filename);
@@ -1048,17 +1057,17 @@ js_InitExceptionClasses(JSContext *cx, J
         JS_ASSERT(proto->privateData == NULL);
 
         if (i == JSEXN_ERR)
             error_proto = proto;
 
         /* Add properties to the prototype. */
         JSAutoResolveFlags rf(cx, JSRESOLVE_QUALIFIED | JSRESOLVE_DECLARING);
         if (!js_DefineNativeProperty(cx, proto, nameId, StringValue(atom),
-                                     PropertyStub, StrictPropertyStub, 
+                                     PropertyStub, StrictPropertyStub,
                                      JSPROP_ENUMERATE, 0, 0, NULL) ||
             !js_DefineNativeProperty(cx, proto, messageId, empty,
                                      PropertyStub, StrictPropertyStub,
                                      JSPROP_ENUMERATE, 0, 0, NULL) ||
             !js_DefineNativeProperty(cx, proto, fileNameId, empty,
                                      PropertyStub, StrictPropertyStub,
                                      JSPROP_ENUMERATE, 0, 0, NULL) ||
             !js_DefineNativeProperty(cx, proto, lineNumberId, Valueify(JSVAL_ZERO),
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_5/misc/error-undefined-message.js
@@ -0,0 +1,7 @@
+// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/licenses/publicdomain/
+
+assertEq(new Error().hasOwnProperty('message'), false);
+assertEq(new Error(undefined).hasOwnProperty('message'), false);
+
+reportCompare(0, 0, 'ok');
--- a/js/src/tests/ecma_5/misc/jstests.list
+++ b/js/src/tests/ecma_5/misc/jstests.list
@@ -4,8 +4,9 @@ script redeclare-var-non-writable-proper
 script enumerate-undefined.js
 script unwrapped-no-such-method.js
 script explicit-undefined-optional-argument.js
 script function-definition-eval.js
 skip-if(!xulRuntime.shell) script function-definition-evaluate.js # needs evaluate()
 script future-reserved-words.js
 script builtin-methods-reject-null-undefined-this.js
 script regress-bug632003.js
+script error-undefined-message.js