From 48acf7738983924b2c2bce90e0d46e37133392e4 Mon Sep 17 00:00:00 2001 From: "ager@chromium.org" Date: Thu, 13 Jan 2011 06:56:54 +0000 Subject: [PATCH] Do not allow accessors to intercept getting/setting properties on error objects under construction and string conversions. Review URL: http://codereview.chromium.org/6146009 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6291 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/messages.js | 14 +++++++++++--- test/mjsunit/error-constructors.js | 21 ++++++++++++++++++++- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/messages.js b/src/messages.js index c19f4a9a6..441244bc8 100644 --- a/src/messages.js +++ b/src/messages.js @@ -946,12 +946,20 @@ function DefineError(f) { f.prototype.name = name; %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); if (m === kAddMessageAccessorsMarker) { + // DefineOneShotAccessor always inserts a message property and + // ignores setters. DefineOneShotAccessor(this, 'message', function (obj) { return FormatMessage({type: obj.type, args: obj.arguments}); }); } else if (!IS_UNDEFINED(m)) { - this.message = ToString(m); + %IgnoreAttributesAndSetProperty(this, 'message', ToString(m)); } captureStackTrace(this, f); } else { @@ -992,8 +1000,8 @@ $Error.prototype.message = ''; if (type && !this.hasOwnProperty("message")) { return this.name + ": " + FormatMessage({ type: type, args: this.arguments }); } - var message = this.message; - return this.name + (message ? (": " + message) : ""); + var message = this.hasOwnProperty("message") ? (": " + this.message) : ""; + return this.name + message; }, DONT_ENUM); diff --git a/test/mjsunit/error-constructors.js b/test/mjsunit/error-constructors.js index ca2aa060a..6b7671d19 100644 --- a/test/mjsunit/error-constructors.js +++ b/test/mjsunit/error-constructors.js @@ -1,4 +1,4 @@ -// Copyright 2009 the V8 project authors. All rights reserved. +// Copyright 2011 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -30,3 +30,22 @@ assertFalse(e.hasOwnProperty('message')); Error.prototype.toString = Object.prototype.toString; assertEquals("[object Error]", Error.prototype.toString()); assertEquals(Object.prototype, Error.prototype.__proto__); + +// Check that error construction does not call setters for the +// properties on error objects in prototypes. +function fail() { assertTrue(false); }; +ReferenceError.prototype.__defineSetter__('stack', fail); +ReferenceError.prototype.__defineSetter__('message', fail); +ReferenceError.prototype.__defineSetter__('type', fail); +ReferenceError.prototype.__defineSetter__('arguments', fail); +var e0 = new ReferenceError(); +var e1 = new ReferenceError('123'); +assertTrue(e1.hasOwnProperty('message')); +assertTrue(e0.hasOwnProperty('stack')); +assertTrue(e1.hasOwnProperty('stack')); +assertTrue(e0.hasOwnProperty('type')); +assertTrue(e1.hasOwnProperty('type')); +assertTrue(e0.hasOwnProperty('arguments')); +assertTrue(e1.hasOwnProperty('arguments')); + + -- 2.34.1