From: yangguo@chromium.org Date: Mon, 12 Nov 2012 10:33:20 +0000 (+0000) Subject: Make formatting error message side-effect-free. X-Git-Tag: upstream/4.7.83~15684 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4cca6c60817cb3e89a42c4e3a26a7a691c91fbe8;p=platform%2Fupstream%2Fv8.git Make formatting error message side-effect-free. BUG=v8:2398 Review URL: https://chromiumcodereview.appspot.com/11359130 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12926 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/isolate.cc b/src/isolate.cc index 75e15a4..b077a70 100644 --- a/src/isolate.cc +++ b/src/isolate.cc @@ -1138,6 +1138,14 @@ void Isolate::DoThrow(Object* exception, MessageLocation* location) { stack_trace_for_uncaught_exceptions_options_); } } + // Stringify custom error objects for the message object. + if (exception_handle->IsJSObject() && !IsErrorObject(exception_handle)) { + bool failed = false; + exception_handle = Execution::ToString(exception_handle, &failed); + if (failed) { + exception_handle = factory()->LookupAsciiSymbol("exception"); + } + } Handle message_obj = MessageHandler::MakeMessageObject( "uncaught_exception", location, diff --git a/src/messages.js b/src/messages.js index 58f0db0..f04bed9 100644 --- a/src/messages.js +++ b/src/messages.js @@ -167,7 +167,7 @@ function FormatString(format, args) { if (arg_num < 4) { // str is one of %0, %1, %2 or %3. try { - str = ToDetailString(args[arg_num]); + str = NoSideEffectToString(args[arg_num]); } catch (e) { if (%IsJSModule(args[arg_num])) str = "module"; @@ -184,6 +184,26 @@ function FormatString(format, args) { } +function NoSideEffectToString(obj) { + if (IS_STRING(obj)) return obj; + if (IS_NUMBER(obj)) return %_NumberToString(obj); + if (IS_BOOLEAN(obj)) return x ? 'true' : 'false'; + if (IS_UNDEFINED(obj)) return 'undefined'; + if (IS_NULL(obj)) return 'null'; + if (IS_OBJECT(obj) && %GetDataProperty(obj, "toString") === ObjectToString) { + var constructor = obj.constructor; + if (typeof constructor == "function") { + var constructorName = constructor.name; + if (IS_STRING(constructorName) && constructorName !== "") { + return "#<" + constructorName + ">"; + } + } + } + if (IsNativeErrorObject(obj)) return %_CallFunction(obj, ErrorToString); + return %_CallFunction(obj, ObjectToString); +} + + // To check if something is a native error we need to check the // concrete native error types. It is not sufficient to use instanceof // since it possible to create an object that has Error.prototype on diff --git a/src/runtime.cc b/src/runtime.cc index fb40d5e..11ba4c8 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -4238,6 +4238,33 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) { } +// Return property without being observable by accessors or interceptors. +RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDataProperty) { + ASSERT(args.length() == 2); + CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); + CONVERT_ARG_HANDLE_CHECKED(String, key, 1); + LookupResult lookup(isolate); + object->LookupRealNamedProperty(*key, &lookup); + if (!lookup.IsFound()) return isolate->heap()->undefined_value(); + switch (lookup.type()) { + case NORMAL: + return lookup.holder()->GetNormalizedProperty(&lookup); + case FIELD: + return lookup.holder()->FastPropertyAt(lookup.GetFieldIndex()); + case CONSTANT_FUNCTION: + return lookup.GetConstantFunction(); + case CALLBACKS: + case HANDLER: + case INTERCEPTOR: + case TRANSITION: + return isolate->heap()->undefined_value(); + case NONEXISTENT: + UNREACHABLE(); + } + return isolate->heap()->undefined_value(); +} + + MaybeObject* Runtime::SetObjectProperty(Isolate* isolate, Handle object, Handle key, diff --git a/src/runtime.h b/src/runtime.h index 4f8d1d7..f63844c 100644 --- a/src/runtime.h +++ b/src/runtime.h @@ -267,6 +267,7 @@ namespace internal { F(DefineOrRedefineDataProperty, 4, 1) \ F(DefineOrRedefineAccessorProperty, 5, 1) \ F(IgnoreAttributesAndSetProperty, -1 /* 3 or 4 */, 1) \ + F(GetDataProperty, 2, 1) \ \ /* Arrays */ \ F(RemoveArrayHoles, 2, 1) \ diff --git a/test/mjsunit/regress/regress-2398.js b/test/mjsunit/regress/regress-2398.js new file mode 100644 index 0000000..1c66e7f --- /dev/null +++ b/test/mjsunit/regress/regress-2398.js @@ -0,0 +1,41 @@ +// Copyright 2012 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: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"use strict"; + +var observed = false; + +var object = { get toString() { observed = true; } }; +Object.defineProperty(object, "ro", { value: 1 }); + +try { + object.ro = 2; // TypeError caused by trying to write to read-only. +} catch (e) { + e.message; // Forces formatting of the message object. +} + +assertFalse(observed);