From 4032d2165efc635d4371ecb5407c216c2988ff17 Mon Sep 17 00:00:00 2001 From: "ricow@chromium.org" Date: Wed, 15 Jun 2011 13:54:40 +0000 Subject: [PATCH] Make name and message non-enumerable on Error object (this is a partial fix for issue 1215) 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 | 41 ++++++++++++++++++++++++++++---------- test/mjsunit/error-constructors.js | 21 +++++++++++++++++++ 2 files changed, 52 insertions(+), 10 deletions(-) diff --git a/src/messages.js b/src/messages.js index f436018..8da1ca4 100644 --- a/src/messages.js +++ b/src/messages.js @@ -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. diff --git a/test/mjsunit/error-constructors.js b/test/mjsunit/error-constructors.js index 8f463fc..966a162 100644 --- a/test/mjsunit/error-constructors.js +++ b/test/mjsunit/error-constructors.js @@ -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(); +} -- 2.7.4