Commit 4783d3c3 authored by yangguo@chromium.org's avatar yangguo@chromium.org

Remove 'type' and 'arguments' properties from Error object.

R=svenpanne@chromium.org
BUG=v8:2397

Review URL: https://chromiumcodereview.appspot.com/11358214

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12956 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 8a210a78
...@@ -252,13 +252,8 @@ function ToDetailString(obj) { ...@@ -252,13 +252,8 @@ function ToDetailString(obj) {
function MakeGenericError(constructor, type, args) { function MakeGenericError(constructor, type, args) {
if (IS_UNDEFINED(args)) { if (IS_UNDEFINED(args)) args = [];
args = []; return new constructor(FormatMessage(type, args));
}
var e = new constructor(FormatMessage(type, args));
e.type = type;
e.arguments = args;
return e;
} }
...@@ -1143,8 +1138,6 @@ function SetUpError() { ...@@ -1143,8 +1138,6 @@ function SetUpError() {
// object. This avoids going through getters and setters defined // object. This avoids going through getters and setters defined
// on prototype objects. // on prototype objects.
%IgnoreAttributesAndSetProperty(this, 'stack', void 0, DONT_ENUM); %IgnoreAttributesAndSetProperty(this, 'stack', void 0, DONT_ENUM);
%IgnoreAttributesAndSetProperty(this, 'arguments', void 0, DONT_ENUM);
%IgnoreAttributesAndSetProperty(this, 'type', void 0, DONT_ENUM);
if (!IS_UNDEFINED(m)) { if (!IS_UNDEFINED(m)) {
%IgnoreAttributesAndSetProperty( %IgnoreAttributesAndSetProperty(
this, 'message', ToString(m), DONT_ENUM); this, 'message', ToString(m), DONT_ENUM);
...@@ -1204,7 +1197,6 @@ function GetPropertyWithoutInvokingMonkeyGetters(error, name) { ...@@ -1204,7 +1197,6 @@ function GetPropertyWithoutInvokingMonkeyGetters(error, name) {
function ErrorToStringDetectCycle(error) { function ErrorToStringDetectCycle(error) {
if (!%PushIfAbsent(visited_errors, error)) throw cyclic_error_marker; if (!%PushIfAbsent(visited_errors, error)) throw cyclic_error_marker;
try { try {
var type = GetPropertyWithoutInvokingMonkeyGetters(error, "type");
var name = GetPropertyWithoutInvokingMonkeyGetters(error, "name"); var name = GetPropertyWithoutInvokingMonkeyGetters(error, "name");
name = IS_UNDEFINED(name) ? "Error" : TO_STRING_INLINE(name); name = IS_UNDEFINED(name) ? "Error" : TO_STRING_INLINE(name);
var message = GetPropertyWithoutInvokingMonkeyGetters(error, "message"); var message = GetPropertyWithoutInvokingMonkeyGetters(error, "message");
......
...@@ -1041,6 +1041,31 @@ TEST(ScopePositions) { ...@@ -1041,6 +1041,31 @@ TEST(ScopePositions) {
} }
i::Handle<i::String> FormatMessage(i::ScriptDataImpl* data) {
i::Handle<i::String> format = v8::Utils::OpenHandle(
*v8::String::New(data->BuildMessage()));
i::Vector<const char*> args = data->BuildArgs();
i::Handle<i::JSArray> args_array = FACTORY->NewJSArray(args.length());
for (int i = 0; i < args.length(); i++) {
i::JSArray::SetElement(args_array,
i,
v8::Utils::OpenHandle(*v8::String::New(args[i])),
NONE,
i::kNonStrictMode);
}
i::Handle<i::JSObject> builtins(i::Isolate::Current()->js_builtins_object());
i::Handle<i::Object> format_fun =
i::GetProperty(builtins, "FormatMessage");
i::Handle<i::Object> arg_handles[] = { format, args_array };
bool has_exception = false;
i::Handle<i::Object> result =
i::Execution::Call(format_fun, builtins, 2, arg_handles, &has_exception);
CHECK(!has_exception);
CHECK(result->IsString());
return i::Handle<i::String>::cast(result);
}
void TestParserSync(i::Handle<i::String> source, int flags) { void TestParserSync(i::Handle<i::String> source, int flags) {
uintptr_t stack_limit = i::Isolate::Current()->stack_guard()->real_climit(); uintptr_t stack_limit = i::Isolate::Current()->stack_guard()->real_climit();
bool harmony_scoping = ((i::kLanguageModeMask & flags) == i::EXTENDED_MODE); bool harmony_scoping = ((i::kLanguageModeMask & flags) == i::EXTENDED_MODE);
...@@ -1067,53 +1092,50 @@ void TestParserSync(i::Handle<i::String> source, int flags) { ...@@ -1067,53 +1092,50 @@ void TestParserSync(i::Handle<i::String> source, int flags) {
i::FunctionLiteral* function = parser.ParseProgram(); i::FunctionLiteral* function = parser.ParseProgram();
i::FLAG_harmony_scoping = save_harmony_scoping; i::FLAG_harmony_scoping = save_harmony_scoping;
i::String* type_string = NULL; // Check that preparsing fails iff parsing fails.
if (function == NULL) { if (function == NULL) {
// Extract exception from the parser. // Extract exception from the parser.
i::Handle<i::String> type_symbol = FACTORY->LookupAsciiSymbol("type");
CHECK(i::Isolate::Current()->has_pending_exception()); CHECK(i::Isolate::Current()->has_pending_exception());
i::MaybeObject* maybe_object = i::Isolate::Current()->pending_exception(); i::MaybeObject* maybe_object = i::Isolate::Current()->pending_exception();
i::JSObject* exception = NULL; i::JSObject* exception = NULL;
CHECK(maybe_object->To(&exception)); CHECK(maybe_object->To(&exception));
i::Handle<i::JSObject> exception_handle(exception);
i::Handle<i::String> message_string =
i::GetProperty(exception_handle, "message");
// Get the type string. if (!data.has_error()) {
maybe_object = exception->GetProperty(*type_symbol); i::OS::Print(
CHECK(maybe_object->To(&type_string)); "Parser failed on:\n"
} "\t%s\n"
"with error:\n"
// Check that preparsing fails iff parsing fails. "\t%s\n"
if (data.has_error() && function != NULL) { "However, the preparser succeeded",
i::OS::Print( *source->ToCString(), *message_string->ToCString());
"Preparser failed on:\n" CHECK(false);
"\t%s\n" }
"with error:\n" // Check that preparser and parser produce the same error.
"\t%s\n" i::Handle<i::String> preparser_message = FormatMessage(&data);
"However, the parser succeeded", if (!message_string->Equals(*preparser_message)) {
*source->ToCString(), data.BuildMessage());
CHECK(false);
} else if (!data.has_error() && function == NULL) {
i::OS::Print(
"Parser failed on:\n"
"\t%s\n"
"with error:\n"
"\t%s\n"
"However, the preparser succeeded",
*source->ToCString(), *type_string->ToCString());
CHECK(false);
}
// Check that preparser and parser produce the same error.
if (function == NULL) {
if (!type_string->IsEqualTo(i::CStrVector(data.BuildMessage()))) {
i::OS::Print( i::OS::Print(
"Expected parser and preparser to produce the same error on:\n" "Expected parser and preparser to produce the same error on:\n"
"\t%s\n" "\t%s\n"
"However, found the following error messages\n" "However, found the following error messages\n"
"\tparser: %s\n" "\tparser: %s\n"
"\tpreparser: %s\n", "\tpreparser: %s\n",
*source->ToCString(), *type_string->ToCString(), data.BuildMessage()); *source->ToCString(),
*message_string->ToCString(),
*preparser_message->ToCString());
CHECK(false); CHECK(false);
} }
} else if (data.has_error()) {
i::OS::Print(
"Preparser failed on:\n"
"\t%s\n"
"with error:\n"
"\t%s\n"
"However, the parser succeeded",
*source->ToCString(), *FormatMessage(&data)->ToCString());
CHECK(false);
} }
} }
......
...@@ -418,8 +418,8 @@ try { ...@@ -418,8 +418,8 @@ try {
exception = true; exception = true;
assertTrue(e instanceof TypeError, assertTrue(e instanceof TypeError,
"reduce callback not a function not throwing TypeError"); "reduce callback not a function not throwing TypeError");
assertEquals("called_non_callable", e.type, assertTrue(e.message.indexOf(" is not a function") >= 0,
"reduce non function TypeError type"); "reduce non function TypeError type");
} }
assertTrue(exception); assertTrue(exception);
...@@ -430,8 +430,8 @@ try { ...@@ -430,8 +430,8 @@ try {
exception = true; exception = true;
assertTrue(e instanceof TypeError, assertTrue(e instanceof TypeError,
"reduceRight callback not a function not throwing TypeError"); "reduceRight callback not a function not throwing TypeError");
assertEquals("called_non_callable", e.type, assertTrue(e.message.indexOf(" is not a function") >= 0,
"reduceRight non function TypeError type"); "reduceRight non function TypeError type");
} }
assertTrue(exception); assertTrue(exception);
...@@ -442,7 +442,7 @@ try { ...@@ -442,7 +442,7 @@ try {
exception = true; exception = true;
assertTrue(e instanceof TypeError, assertTrue(e instanceof TypeError,
"reduce no initial value not throwing TypeError"); "reduce no initial value not throwing TypeError");
assertEquals("reduce_no_initial", e.type, assertEquals("Reduce of empty array with no initial value", e.message,
"reduce no initial TypeError type"); "reduce no initial TypeError type");
} }
assertTrue(exception); assertTrue(exception);
...@@ -454,7 +454,7 @@ try { ...@@ -454,7 +454,7 @@ try {
exception = true; exception = true;
assertTrue(e instanceof TypeError, assertTrue(e instanceof TypeError,
"reduceRight no initial value not throwing TypeError"); "reduceRight no initial value not throwing TypeError");
assertEquals("reduce_no_initial", e.type, assertEquals("Reduce of empty array with no initial value", e.message,
"reduceRight no initial TypeError type"); "reduceRight no initial TypeError type");
} }
assertTrue(exception); assertTrue(exception);
...@@ -466,7 +466,7 @@ try { ...@@ -466,7 +466,7 @@ try {
exception = true; exception = true;
assertTrue(e instanceof TypeError, assertTrue(e instanceof TypeError,
"reduce sparse no initial value not throwing TypeError"); "reduce sparse no initial value not throwing TypeError");
assertEquals("reduce_no_initial", e.type, assertEquals("Reduce of empty array with no initial value", e.message,
"reduce no initial TypeError type"); "reduce no initial TypeError type");
} }
assertTrue(exception); assertTrue(exception);
...@@ -478,7 +478,7 @@ try { ...@@ -478,7 +478,7 @@ try {
exception = true; exception = true;
assertTrue(e instanceof TypeError, assertTrue(e instanceof TypeError,
"reduceRight sparse no initial value not throwing TypeError"); "reduceRight sparse no initial value not throwing TypeError");
assertEquals("reduce_no_initial", e.type, assertEquals("Reduce of empty array with no initial value", e.message,
"reduceRight no initial TypeError type"); "reduceRight no initial TypeError type");
} }
assertTrue(exception); assertTrue(exception);
......
...@@ -36,10 +36,6 @@ assertFalse(desc['enumerable']); ...@@ -36,10 +36,6 @@ assertFalse(desc['enumerable']);
var e = new Error("foobar"); var e = new Error("foobar");
desc = Object.getOwnPropertyDescriptor(e, 'message'); desc = Object.getOwnPropertyDescriptor(e, 'message');
assertFalse(desc['enumerable']); assertFalse(desc['enumerable']);
desc = Object.getOwnPropertyDescriptor(e, 'arguments');
assertFalse(desc['enumerable']);
desc = Object.getOwnPropertyDescriptor(e, 'type');
assertFalse(desc['enumerable']);
desc = Object.getOwnPropertyDescriptor(e, 'stack'); desc = Object.getOwnPropertyDescriptor(e, 'stack');
assertFalse(desc['enumerable']); assertFalse(desc['enumerable']);
...@@ -57,26 +53,17 @@ for (var v in e) { ...@@ -57,26 +53,17 @@ for (var v in e) {
function fail() { assertUnreachable(); }; function fail() { assertUnreachable(); };
ReferenceError.prototype.__defineSetter__('name', fail); ReferenceError.prototype.__defineSetter__('name', fail);
ReferenceError.prototype.__defineSetter__('message', fail); ReferenceError.prototype.__defineSetter__('message', fail);
ReferenceError.prototype.__defineSetter__('type', fail);
ReferenceError.prototype.__defineSetter__('arguments', fail);
ReferenceError.prototype.__defineSetter__('stack', fail); ReferenceError.prototype.__defineSetter__('stack', fail);
var e = new ReferenceError(); var e = new ReferenceError();
assertTrue(e.hasOwnProperty('stack')); assertTrue(e.hasOwnProperty('stack'));
assertTrue(e.hasOwnProperty('type'));
assertTrue(e.hasOwnProperty('arguments'));
var e = new ReferenceError('123'); var e = new ReferenceError('123');
assertTrue(e.hasOwnProperty('message')); assertTrue(e.hasOwnProperty('message'));
assertTrue(e.hasOwnProperty('stack')); assertTrue(e.hasOwnProperty('stack'));
assertTrue(e.hasOwnProperty('type'));
assertTrue(e.hasOwnProperty('arguments'));
var e = %MakeReferenceError("my_test_error", [0, 1]); var e = %MakeReferenceError("my_test_error", [0, 1]);
assertTrue(e.hasOwnProperty('stack')); assertTrue(e.hasOwnProperty('stack'));
assertTrue(e.hasOwnProperty('type'));
assertTrue(e.hasOwnProperty('arguments'));
assertEquals("my_test_error", e.type)
// Check that intercepting property access from toString is prevented for // Check that intercepting property access from toString is prevented for
// compiler errors. This is not specified, but allowing interception // compiler errors. This is not specified, but allowing interception
...@@ -86,7 +73,7 @@ var errors = [SyntaxError, ReferenceError, TypeError]; ...@@ -86,7 +73,7 @@ var errors = [SyntaxError, ReferenceError, TypeError];
for (var i in errors) { for (var i in errors) {
var name = errors[i].prototype.toString(); var name = errors[i].prototype.toString();
// Monkey-patch prototype. // Monkey-patch prototype.
var props = ["name", "message", "type", "arguments", "stack"]; var props = ["name", "message", "stack"];
for (var j in props) { for (var j in props) {
errors[i].prototype.__defineGetter__(props[j], fail); errors[i].prototype.__defineGetter__(props[j], fail);
} }
......
...@@ -150,6 +150,11 @@ var reducing_functions = ...@@ -150,6 +150,11 @@ var reducing_functions =
[Array.prototype.reduce, [Array.prototype.reduce,
Array.prototype.reduceRight]; Array.prototype.reduceRight];
function checkExpectedMessage(e) {
assertTrue(e.message.indexOf("called on null or undefined") >= 0 ||
e.message.indexOf("Cannot convert null to object") >= 0);
}
// Test that all natives using the ToObject call throw the right exception. // Test that all natives using the ToObject call throw the right exception.
for (var i = 0; i < should_throw_on_null_and_undefined.length; i++) { for (var i = 0; i < should_throw_on_null_and_undefined.length; i++) {
// Sanity check that all functions are correct // Sanity check that all functions are correct
...@@ -166,8 +171,7 @@ for (var i = 0; i < should_throw_on_null_and_undefined.length; i++) { ...@@ -166,8 +171,7 @@ for (var i = 0; i < should_throw_on_null_and_undefined.length; i++) {
should_throw_on_null_and_undefined[i].call(null); should_throw_on_null_and_undefined[i].call(null);
} catch (e) { } catch (e) {
exception = true; exception = true;
assertTrue("called_on_null_or_undefined" == e.type || checkExpectedMessage(e);
"null_to_object" == e.type);
} }
assertTrue(exception); assertTrue(exception);
...@@ -176,8 +180,7 @@ for (var i = 0; i < should_throw_on_null_and_undefined.length; i++) { ...@@ -176,8 +180,7 @@ for (var i = 0; i < should_throw_on_null_and_undefined.length; i++) {
should_throw_on_null_and_undefined[i].call(undefined); should_throw_on_null_and_undefined[i].call(undefined);
} catch (e) { } catch (e) {
exception = true; exception = true;
assertTrue("called_on_null_or_undefined" == e.type || checkExpectedMessage(e);
"null_to_object" == e.type);
} }
assertTrue(exception); assertTrue(exception);
...@@ -186,8 +189,7 @@ for (var i = 0; i < should_throw_on_null_and_undefined.length; i++) { ...@@ -186,8 +189,7 @@ for (var i = 0; i < should_throw_on_null_and_undefined.length; i++) {
should_throw_on_null_and_undefined[i].apply(null); should_throw_on_null_and_undefined[i].apply(null);
} catch (e) { } catch (e) {
exception = true; exception = true;
assertTrue("called_on_null_or_undefined" == e.type || checkExpectedMessage(e);
"null_to_object" == e.type);
} }
assertTrue(exception); assertTrue(exception);
...@@ -196,8 +198,7 @@ for (var i = 0; i < should_throw_on_null_and_undefined.length; i++) { ...@@ -196,8 +198,7 @@ for (var i = 0; i < should_throw_on_null_and_undefined.length; i++) {
should_throw_on_null_and_undefined[i].apply(undefined); should_throw_on_null_and_undefined[i].apply(undefined);
} catch (e) { } catch (e) {
exception = true; exception = true;
assertTrue("called_on_null_or_undefined" == e.type || checkExpectedMessage(e);
"null_to_object" == e.type);
} }
assertTrue(exception); assertTrue(exception);
} }
...@@ -257,8 +258,7 @@ for (var j = 0; j < mapping_functions.length; j++) { ...@@ -257,8 +258,7 @@ for (var j = 0; j < mapping_functions.length; j++) {
null); null);
} catch (e) { } catch (e) {
exception = true; exception = true;
assertTrue("called_on_null_or_undefined" == e.type || checkExpectedMessage(e);
"null_to_object" == e.type);
} }
assertTrue(exception); assertTrue(exception);
...@@ -269,8 +269,7 @@ for (var j = 0; j < mapping_functions.length; j++) { ...@@ -269,8 +269,7 @@ for (var j = 0; j < mapping_functions.length; j++) {
undefined); undefined);
} catch (e) { } catch (e) {
exception = true; exception = true;
assertTrue("called_on_null_or_undefined" == e.type || checkExpectedMessage(e);
"null_to_object" == e.type);
} }
assertTrue(exception); assertTrue(exception);
} }
...@@ -311,8 +310,7 @@ for (var j = 0; j < reducing_functions.length; j++) { ...@@ -311,8 +310,7 @@ for (var j = 0; j < reducing_functions.length; j++) {
reducing_functions[j].call(array, should_throw_on_null_and_undefined[i]); reducing_functions[j].call(array, should_throw_on_null_and_undefined[i]);
} catch (e) { } catch (e) {
exception = true; exception = true;
assertTrue("called_on_null_or_undefined" == e.type || checkExpectedMessage(e);
"null_to_object" == e.type);
} }
assertTrue(exception); assertTrue(exception);
...@@ -321,8 +319,7 @@ for (var j = 0; j < reducing_functions.length; j++) { ...@@ -321,8 +319,7 @@ for (var j = 0; j < reducing_functions.length; j++) {
reducing_functions[j].call(array, should_throw_on_null_and_undefined[i]); reducing_functions[j].call(array, should_throw_on_null_and_undefined[i]);
} catch (e) { } catch (e) {
exception = true; exception = true;
assertTrue("called_on_null_or_undefined" == e.type || checkExpectedMessage(e);
"null_to_object" == e.type);
} }
assertTrue(exception); assertTrue(exception);
} }
......
...@@ -34,7 +34,7 @@ for (var i = 0; i < invalid_this.length; i++) { ...@@ -34,7 +34,7 @@ for (var i = 0; i < invalid_this.length; i++) {
Error.prototype.toString.call(invalid_this[i]); Error.prototype.toString.call(invalid_this[i]);
} catch (e) { } catch (e) {
exception = true; exception = true;
assertTrue("called_on_non_object" == e.type); assertEquals("Error.prototype.toString called on non-object", e.message);
} }
assertTrue(exception); assertTrue(exception);
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment