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
This commit is contained in:
ricow@chromium.org 2011-06-15 13:54:40 +00:00
parent 939011bb25
commit 4032d2165e
2 changed files with 52 additions and 10 deletions

View 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.

View 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();
}