Make name and message non-enumerable on Error object (this is a partial fix for issue...
authorricow@chromium.org <ricow@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 15 Jun 2011 13:54:40 +0000 (13:54 +0000)
committerricow@chromium.org <ricow@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 15 Jun 2011 13:54:40 +0000 (13:54 +0000)
Review URL: http://codereview.chromium.org/7172011

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8299 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/messages.js
test/mjsunit/error-constructors.js

index f436018..8da1ca4 100644 (file)
@@ -684,18 +684,24 @@ function DefineOneShotAccessor(obj, name, fun) {
   // can't rely on 'this' being the same as 'obj'.
   var hasBeenSet = false;
   var value;
-  obj.__defineGetter__(name, function () {
+  function getter() {
     if (hasBeenSet) {
       return value;
     }
     hasBeenSet = true;
     value = fun(obj);
     return value;
-  });
-  obj.__defineSetter__(name, function (v) {
+  }
+  function setter(v) {
     hasBeenSet = true;
     value = v;
-  });
+  }
+  var desc = { get: getter,
+               set: setter,
+               enumerable: false,
+               configurable: true };
+  desc = ToPropertyDescriptor(desc);
+  DefineOwnProperty(obj, name, desc, true);
 }
 
 function CallSite(receiver, fun, pos) {
@@ -999,15 +1005,15 @@ function DefineError(f) {
   // overwriting allows leaks of error objects between script blocks
   // in the same context in a browser setting. Therefore we fix the
   // name.
-  %SetProperty(f.prototype, "name", name, READ_ONLY | DONT_DELETE);
+  %SetProperty(f.prototype, "name", name, DONT_ENUM | DONT_DELETE | READ_ONLY);
   %SetCode(f, function(m) {
     if (%_IsConstructCall()) {
       // Define all the expected properties directly on the error
       // object. This avoids going through getters and setters defined
       // on prototype objects.
-      %IgnoreAttributesAndSetProperty(this, 'stack', void 0);
-      %IgnoreAttributesAndSetProperty(this, 'arguments', void 0);
-      %IgnoreAttributesAndSetProperty(this, 'type', void 0);
+      %IgnoreAttributesAndSetProperty(this, 'stack', void 0, DONT_ENUM);
+      %IgnoreAttributesAndSetProperty(this, 'arguments', void 0, DONT_ENUM);
+      %IgnoreAttributesAndSetProperty(this, 'type', void 0, DONT_ENUM);
       if (m === kAddMessageAccessorsMarker) {
         // DefineOneShotAccessor always inserts a message property and
         // ignores setters.
@@ -1015,7 +1021,10 @@ function DefineError(f) {
             return FormatMessage(%NewMessageObject(obj.type, obj.arguments));
         });
       } else if (!IS_UNDEFINED(m)) {
-        %IgnoreAttributesAndSetProperty(this, 'message', ToString(m));
+        %IgnoreAttributesAndSetProperty(this,
+                                        'message',
+                                        ToString(m),
+                                        DONT_ENUM);
       }
       captureStackTrace(this, f);
     } else {
@@ -1050,7 +1059,19 @@ DefineError(function URIError() { });
 $Error.captureStackTrace = captureStackTrace;
 
 // Setup extra properties of the Error.prototype object.
-$Error.prototype.message = '';
+function setErrorMessage() {
+  var desc = {value: '',
+              enumerable: false,
+              configurable: true,
+              writable: true };
+  DefineOwnProperty($Error.prototype,
+                    'message',
+                    ToPropertyDescriptor(desc),
+                    true);
+
+}
+
+setErrorMessage();
 
 // Global list of error objects visited during errorToString. This is
 // used to detect cycles in error toString formatting.
index 8f463fc..966a162 100644 (file)
@@ -59,3 +59,24 @@ assertEquals("ReferenceError", ReferenceError.prototype.name);
 ReferenceError.prototype.name = "not a reference error";
 assertEquals("ReferenceError", ReferenceError.prototype.name);
 
+// Check that message and name are not enumerable on Error objects.
+var desc = Object.getOwnPropertyDescriptor(Error.prototype, 'name');
+assertFalse(desc['enumerable']);
+desc = Object.getOwnPropertyDescriptor(Error.prototype, 'message');
+assertFalse(desc['enumerable']);
+
+var e = new Error("foobar");
+desc = Object.getOwnPropertyDescriptor(e, 'message');
+assertFalse(desc['enumerable']);
+desc = Object.getOwnPropertyDescriptor(e, 'arguments');
+assertFalse(desc['enumerable']);
+desc = Object.getOwnPropertyDescriptor(e, 'type');
+assertFalse(desc['enumerable']);
+desc = Object.getOwnPropertyDescriptor(e, 'stack');
+assertFalse(desc['enumerable']);
+
+// name is not tested above, but in addition we should have no enumerable
+// properties, so we simply assert that.
+for (var v in e) {
+  assertUnreachable();
+}