Revision: 6574
Author: [email protected]
Date: Wed Feb  2 05:31:52 2011
Log: A MessageObject is a purely internal object to hold information about
an error message that needs to be generated and reported. This change
hides all of the error information from JavaScript code so user
callbacks cannot get hold of it.

Review URL: http://codereview.chromium.org/6368051
http://code.google.com/p/v8/source/detail?r=6574

Modified:
 /branches/bleeding_edge/include/v8.h
 /branches/bleeding_edge/src/api.cc
 /branches/bleeding_edge/src/bootstrapper.cc
 /branches/bleeding_edge/src/factory.cc
 /branches/bleeding_edge/src/factory.h
 /branches/bleeding_edge/src/heap.cc
 /branches/bleeding_edge/src/heap.h
 /branches/bleeding_edge/src/messages.cc
 /branches/bleeding_edge/src/messages.h
 /branches/bleeding_edge/src/messages.js
 /branches/bleeding_edge/src/objects-debug.cc
 /branches/bleeding_edge/src/objects-inl.h
 /branches/bleeding_edge/src/objects-printer.cc
 /branches/bleeding_edge/src/objects-visiting.cc
 /branches/bleeding_edge/src/objects.cc
 /branches/bleeding_edge/src/objects.h
 /branches/bleeding_edge/src/runtime.cc
 /branches/bleeding_edge/src/runtime.h
 /branches/bleeding_edge/test/cctest/test-api.cc

=======================================
--- /branches/bleeding_edge/include/v8.h        Fri Jan 28 05:41:19 2011
+++ /branches/bleeding_edge/include/v8.h        Wed Feb  2 05:31:52 2011
@@ -3448,7 +3448,7 @@
   static const int kFullStringRepresentationMask = 0x07;
   static const int kExternalTwoByteRepresentationTag = 0x02;

-  static const int kJSObjectType = 0x9f;
+  static const int kJSObjectType = 0xa0;
   static const int kFirstNonstringType = 0x80;
   static const int kProxyType = 0x85;

=======================================
--- /branches/bleeding_edge/src/api.cc  Wed Feb  2 00:14:06 2011
+++ /branches/bleeding_edge/src/api.cc  Wed Feb  2 05:31:52 2011
@@ -1478,11 +1478,11 @@
   }
   ENTER_V8;
   HandleScope scope;
-  i::Handle<i::JSObject> obj =
-      i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
+  i::Handle<i::JSMessageObject> message =
+      i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
   // Return this.script.name.
   i::Handle<i::JSValue> script =
-      i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
+      i::Handle<i::JSValue>::cast(i::Handle<i::Object>(message->script()));
i::Handle<i::Object> resource_name(i::Script::cast(script->value())->name());
   return scope.Close(Utils::ToLocal(resource_name));
 }
@@ -1494,11 +1494,11 @@
   }
   ENTER_V8;
   HandleScope scope;
-  i::Handle<i::JSObject> obj =
-      i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
+  i::Handle<i::JSMessageObject> message =
+      i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
   // Return this.script.data.
   i::Handle<i::JSValue> script =
-      i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
+      i::Handle<i::JSValue>::cast(i::Handle<i::Object>(message->script()));
   i::Handle<i::Object> data(i::Script::cast(script->value())->data());
   return scope.Close(Utils::ToLocal(data));
 }
@@ -1510,9 +1510,9 @@
   }
   ENTER_V8;
   HandleScope scope;
-  i::Handle<i::JSObject> obj =
-      i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
-  i::Handle<i::Object> stackFramesObj = GetProperty(obj, "stackFrames");
+  i::Handle<i::JSMessageObject> message =
+      i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
+  i::Handle<i::Object> stackFramesObj(message->stack_frames());
   if (!stackFramesObj->IsJSArray()) return v8::Handle<v8::StackTrace>();
   i::Handle<i::JSArray> stackTrace =
       i::Handle<i::JSArray>::cast(stackFramesObj);
@@ -1552,6 +1552,7 @@
   ON_BAILOUT("v8::Message::GetLineNumber()", return kNoLineNumberInfo);
   ENTER_V8;
   HandleScope scope;
+
   EXCEPTION_PREAMBLE();
   i::Handle<i::Object> result = CallV8HeapFunction("GetLineNumber",
                                                    Utils::OpenHandle(this),
@@ -1565,9 +1566,9 @@
   if (IsDeadCheck("v8::Message::GetStartPosition()")) return 0;
   ENTER_V8;
   HandleScope scope;
-
-  i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
-  return static_cast<int>(GetProperty(data_obj, "startPos")->Number());
+  i::Handle<i::JSMessageObject> message =
+      i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
+  return message->start_position();
 }


@@ -1575,8 +1576,9 @@
   if (IsDeadCheck("v8::Message::GetEndPosition()")) return 0;
   ENTER_V8;
   HandleScope scope;
-  i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
-  return static_cast<int>(GetProperty(data_obj, "endPos")->Number());
+  i::Handle<i::JSMessageObject> message =
+      i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
+  return message->end_position();
 }


@@ -1606,8 +1608,10 @@
       data_obj,
       &has_pending_exception);
   EXCEPTION_BAILOUT_CHECK(0);
- int start = static_cast<int>(GetProperty(data_obj, "startPos")->Number());
-  int end = static_cast<int>(GetProperty(data_obj, "endPos")->Number());
+  i::Handle<i::JSMessageObject> message =
+      i::Handle<i::JSMessageObject>::cast(data_obj);
+  int start = message->start_position();
+  int end = message->end_position();
   return static_cast<int>(start_col_obj->Number()) + (end - start);
 }

=======================================
--- /branches/bleeding_edge/src/bootstrapper.cc Thu Jan 27 08:17:13 2011
+++ /branches/bleeding_edge/src/bootstrapper.cc Wed Feb  2 05:31:52 2011
@@ -1050,7 +1050,6 @@
   INSTALL_NATIVE(JSFunction, "Instantiate", instantiate_fun);
   INSTALL_NATIVE(JSFunction, "ConfigureTemplateInstance",
                  configure_instance_fun);
-  INSTALL_NATIVE(JSFunction, "MakeMessage", make_message_fun);
INSTALL_NATIVE(JSFunction, "GetStackTraceLine", get_stack_trace_line_fun);
   INSTALL_NATIVE(JSObject, "functionCache", function_cache);
 }
=======================================
--- /branches/bleeding_edge/src/factory.cc      Wed Dec 22 12:14:19 2010
+++ /branches/bleeding_edge/src/factory.cc      Wed Feb  2 05:31:52 2011
@@ -754,6 +754,24 @@
   return shared;
 }

+
+Handle<JSMessageObject> Factory::NewJSMessageObject(
+    Handle<String> type,
+    Handle<JSArray> arguments,
+    int start_position,
+    int end_position,
+    Handle<Object> script,
+    Handle<Object> stack_trace,
+    Handle<Object> stack_frames) {
+  CALL_HEAP_FUNCTION(Heap::AllocateJSMessageObject(*type,
+                                                   *arguments,
+                                                   start_position,
+                                                   end_position,
+                                                   *script,
+                                                   *stack_trace,
+                                                   *stack_frames),
+                     JSMessageObject);
+}

Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(Handle<String> name) {
   CALL_HEAP_FUNCTION(Heap::AllocateSharedFunctionInfo(*name),
=======================================
--- /branches/bleeding_edge/src/factory.h       Wed Dec 22 12:14:19 2010
+++ /branches/bleeding_edge/src/factory.h       Wed Feb  2 05:31:52 2011
@@ -365,6 +365,15 @@
       Handle<SerializedScopeInfo> scope_info);
static Handle<SharedFunctionInfo> NewSharedFunctionInfo(Handle<String> name);

+  static Handle<JSMessageObject> NewJSMessageObject(
+      Handle<String> type,
+      Handle<JSArray> arguments,
+      int start_position,
+      int end_position,
+      Handle<Object> script,
+      Handle<Object> stack_trace,
+      Handle<Object> stack_frames);
+
   static Handle<NumberDictionary> DictionaryAtNumberPut(
       Handle<NumberDictionary>,
       uint32_t key,
=======================================
--- /branches/bleeding_edge/src/heap.cc Tue Jan 25 04:35:06 2011
+++ /branches/bleeding_edge/src/heap.cc Wed Feb  2 05:31:52 2011
@@ -1826,6 +1826,12 @@
   }
   set_shared_function_info_map(Map::cast(obj));

+  { MaybeObject* maybe_obj = AllocateMap(JS_MESSAGE_OBJECT_TYPE,
+                                         JSMessageObject::kSize);
+    if (!maybe_obj->ToObject(&obj)) return false;
+  }
+  set_message_object_map(Map::cast(obj));
+
   ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
   return true;
 }
@@ -2327,6 +2333,32 @@
   share->set_function_token_position(0);
   return result;
 }
+
+
+MaybeObject* Heap::AllocateJSMessageObject(String* type,
+                                           JSArray* arguments,
+                                           int start_position,
+                                           int end_position,
+                                           Object* script,
+                                           Object* stack_trace,
+                                           Object* stack_frames) {
+  Object* result;
+  { MaybeObject* maybe_result = Allocate(message_object_map(), NEW_SPACE);
+    if (!maybe_result->ToObject(&result)) return maybe_result;
+  }
+  JSMessageObject* message = JSMessageObject::cast(result);
+  message->set_properties(Heap::empty_fixed_array());
+  message->set_elements(Heap::empty_fixed_array());
+  message->set_type(type);
+  message->set_arguments(arguments);
+  message->set_start_position(start_position);
+  message->set_end_position(end_position);
+  message->set_script(script);
+  message->set_stack_trace(stack_trace);
+  message->set_stack_frames(stack_frames);
+  return result;
+}
+


 // Returns true for a character in a range.  Both limits are inclusive.
=======================================
--- /branches/bleeding_edge/src/heap.h  Fri Jan 21 15:58:00 2011
+++ /branches/bleeding_edge/src/heap.h  Wed Feb  2 05:31:52 2011
@@ -94,6 +94,7 @@
V(Map, oddball_map, OddballMap) \ V(Map, global_property_cell_map, GlobalPropertyCellMap) \ V(Map, shared_function_info_map, SharedFunctionInfoMap) \ + V(Map, message_object_map, JSMessageObjectMap) \ V(Map, proxy_map, ProxyMap) \ V(Object, nan_value, NanValue) \ V(Object, minus_zero_value, MinusZeroValue) \
@@ -628,6 +629,19 @@
   // Please note this does not perform a garbage collection.
MUST_USE_RESULT static MaybeObject* AllocateSharedFunctionInfo(Object* name);

+  // Allocates a new JSMessageObject object.
+ // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+  // failed.
+  // Please note that this does not perform a garbage collection.
+  MUST_USE_RESULT static MaybeObject* AllocateJSMessageObject(
+      String* type,
+      JSArray* arguments,
+      int start_position,
+      int end_position,
+      Object* script,
+      Object* stack_trace,
+      Object* stack_frames);
+
   // Allocates a new cons string object.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
   // failed.
=======================================
--- /branches/bleeding_edge/src/messages.cc     Tue Dec  7 03:01:02 2010
+++ /branches/bleeding_edge/src/messages.cc     Wed Feb  2 05:31:52 2011
@@ -62,67 +62,45 @@
 }


-Handle<Object> MessageHandler::MakeMessageObject(
+Handle<JSMessageObject> MessageHandler::MakeMessageObject(
     const char* type,
     MessageLocation* loc,
     Vector< Handle<Object> > args,
     Handle<String> stack_trace,
     Handle<JSArray> stack_frames) {
-  // Build error message object
- v8::HandleScope scope; // Instantiate a closeable HandleScope for EscapeFrom.
-  Handle<Object> type_str = Factory::LookupAsciiSymbol(type);
-  Handle<Object> array = Factory::NewJSArray(args.length());
-  for (int i = 0; i < args.length(); i++)
-    SetElement(Handle<JSArray>::cast(array), i, args[i]);
-
-  Handle<JSFunction> fun(Top::global_context()->make_message_fun());
-  int start, end;
-  Handle<Object> script;
+  Handle<String> type_handle = Factory::LookupAsciiSymbol(type);
+  Handle<JSArray> arguments_handle = Factory::NewJSArray(args.length());
+  for (int i = 0; i < args.length(); i++) {
+    SetElement(arguments_handle, i, args[i]);
+  }
+
+  int start = 0;
+  int end = 0;
+  Handle<Object> script_handle = Factory::undefined_value();
   if (loc) {
     start = loc->start_pos();
     end = loc->end_pos();
-    script = GetScriptWrapper(loc->script());
-  } else {
-    start = end = 0;
-    script = Factory::undefined_value();
-  }
-  Handle<Object> start_handle(Smi::FromInt(start));
-  Handle<Object> end_handle(Smi::FromInt(end));
-  Handle<Object> stack_trace_val = stack_trace.is_null()
-    ? Factory::undefined_value()
-    : Handle<Object>::cast(stack_trace);
-  Handle<Object> stack_frames_val =  stack_frames.is_null()
-    ? Factory::undefined_value()
-    : Handle<Object>::cast(stack_frames);
-  const int argc = 7;
-  Object** argv[argc] = { type_str.location(),
-                          array.location(),
-                          start_handle.location(),
-                          end_handle.location(),
-                          script.location(),
-                          stack_trace_val.location(),
-                          stack_frames_val.location() };
-
- // Setup a catch handler to catch exceptions in creating the message. This - // handler is non-verbose to avoid calling MakeMessage recursively in case of
-  // an exception.
-  v8::TryCatch catcher;
-  catcher.SetVerbose(false);
-  catcher.SetCaptureMessage(false);
-
-  // Format the message.
-  bool caught_exception = false;
-  Handle<Object> message =
-      Execution::Call(fun, Factory::undefined_value(), argc, argv,
-                      &caught_exception);
-
-  // If creating the message (in JS code) resulted in an exception, we
-  // skip doing the callback. This usually only happens in case of
-  // stack overflow exceptions being thrown by the parser when the
-  // stack is almost full.
-  if (caught_exception) return Handle<Object>();
-
-  return message.EscapeFrom(&scope);
+    script_handle = GetScriptWrapper(loc->script());
+  }
+
+  Handle<Object> stack_trace_handle = stack_trace.is_null()
+      ? Factory::undefined_value()
+      : Handle<Object>::cast(stack_trace);
+
+  Handle<Object> stack_frames_handle =  stack_frames.is_null()
+      ? Factory::undefined_value()
+      : Handle<Object>::cast(stack_frames);
+
+  Handle<JSMessageObject> message =
+      Factory::NewJSMessageObject(type_handle,
+                                  arguments_handle,
+                                  start,
+                                  end,
+                                  script_handle,
+                                  stack_trace_handle,
+                                  stack_frames_handle);
+
+  return message;
 }


=======================================
--- /branches/bleeding_edge/src/messages.h      Tue Dec  7 03:01:02 2010
+++ /branches/bleeding_edge/src/messages.h      Wed Feb  2 05:31:52 2011
@@ -93,11 +93,12 @@
   static void ReportMessage(const char* msg);

   // Returns a message object for the API to use.
-  static Handle<Object> MakeMessageObject(const char* type,
-                                          MessageLocation* loc,
-                                          Vector< Handle<Object> > args,
-                                          Handle<String> stack_trace,
-                                          Handle<JSArray> stack_frames);
+  static Handle<JSMessageObject> MakeMessageObject(
+      const char* type,
+      MessageLocation* loc,
+      Vector< Handle<Object> > args,
+      Handle<String> stack_trace,
+      Handle<JSArray> stack_frames);

   // Report a formatted message (needs JS allocation).
   static void ReportMessage(MessageLocation* loc, Handle<Object> message);
=======================================
--- /branches/bleeding_edge/src/messages.js     Tue Feb  1 08:08:44 2011
+++ /branches/bleeding_edge/src/messages.js     Wed Feb  2 05:31:52 2011
@@ -55,7 +55,8 @@
 var kReplacementMarkers =
     [ "%0", "%1", "%2", "%3" ]

-function FormatString(format, args) {
+function FormatString(format, message) {
+  var args = %MessageGetArguments(message);
   var result = "";
   var arg_num = 0;
   for (var i = 0; i < format.length; i++) {
@@ -227,15 +228,18 @@
strict_lhs_prefix: ["Prefix increment/decrement may not have eval or arguments operand in strict mode"],
     };
   }
-  var format = kMessages[message.type];
-  if (!format) return "<unknown message " + message.type + ">";
-  return FormatString(format, message.args);
+  var message_type = %MessageGetType(message);
+  var format = kMessages[message_type];
+  if (!format) return "<unknown message " + message_type + ">";
+  return FormatString(format, message);
 }


 function GetLineNumber(message) {
-  if (message.startPos == -1) return kNoLineNumberInfo;
- var location = message.script.locationFromPosition(message.startPos, true);
+  var start_position = %MessageGetStartPosition(message);
+  if (start_position == -1) return kNoLineNumberInfo;
+  var script = %MessageGetScript(message);
+  var location = script.locationFromPosition(start_position, true);
   if (location == null) return kNoLineNumberInfo;
   return location.line + 1;
 }
@@ -244,7 +248,9 @@
 // Returns the source code line containing the given source
 // position, or the empty string if the position is invalid.
 function GetSourceLine(message) {
- var location = message.script.locationFromPosition(message.startPos, true);
+  var script = %MessageGetScript(message);
+  var start_position = %MessageGetStartPosition(message);
+  var location = script.locationFromPosition(start_position, true);
   if (location == null) return "";
   location.restrict();
   return location.sourceText();
@@ -623,29 +629,12 @@
 // Returns the offset of the given position within the containing
 // line.
 function GetPositionInLine(message) {
- var location = message.script.locationFromPosition(message.startPos, false);
+  var script = %MessageGetScript(message);
+  var start_position = %MessageGetStartPosition(message);
+  var location = script.locationFromPosition(start_position, false);
   if (location == null) return -1;
   location.restrict();
-  return message.startPos - location.start;
-}
-
-
-function ErrorMessage(type, args, startPos, endPos, script, stackTrace,
-                      stackFrames) {
-  this.startPos = startPos;
-  this.endPos = endPos;
-  this.type = type;
-  this.args = args;
-  this.script = script;
-  this.stackTrace = stackTrace;
-  this.stackFrames = stackFrames;
-}
-
-
-function MakeMessage(type, args, startPos, endPos, script, stackTrace,
-                     stackFrames) {
-  return new ErrorMessage(type, args, startPos, endPos, script, stackTrace,
-                          stackFrames);
+  return start_position - location.start;
 }


@@ -992,7 +981,7 @@
         // DefineOneShotAccessor always inserts a message property and
         // ignores setters.
         DefineOneShotAccessor(this, 'message', function (obj) {
-          return FormatMessage({type: obj.type, args: obj.arguments});
+ return FormatMessage(%NewMessageObject(obj.type, obj.arguments));
         });
       } else if (!IS_UNDEFINED(m)) {
         %IgnoreAttributesAndSetProperty(this, 'message', ToString(m));
@@ -1006,11 +995,12 @@

 function captureStackTrace(obj, cons_opt) {
   var stackTraceLimit = $Error.stackTraceLimit;
-  if (!stackTraceLimit) return;
+  if (!stackTraceLimit || !IS_NUMBER(stackTraceLimit)) return;
   if (stackTraceLimit < 0 || stackTraceLimit > 10000)
     stackTraceLimit = 10000;
- var raw_stack = %CollectStackTrace(cons_opt ? cons_opt : captureStackTrace,
-      stackTraceLimit);
+  var raw_stack = %CollectStackTrace(cons_opt
+                                     ? cons_opt
+                                     : captureStackTrace, stackTraceLimit);
   DefineOneShotAccessor(obj, 'stack', function (obj) {
     return FormatRawStackTrace(obj, raw_stack);
   });
@@ -1041,7 +1031,7 @@
   try {
     var type = this.type;
     if (type && !%_CallFunction(this, "message", ObjectHasOwnProperty)) {
-      var formatted = FormatMessage({ type: type, args: this.arguments });
+ var formatted = FormatMessage(%NewMessageObject(type, this.arguments));
       return this.name + ": " + formatted;
     }
     var message = %_CallFunction(this, "message", ObjectHasOwnProperty)
=======================================
--- /branches/bleeding_edge/src/objects-debug.cc        Mon Jan 17 08:54:56 2011
+++ /branches/bleeding_edge/src/objects-debug.cc        Wed Feb  2 05:31:52 2011
@@ -158,6 +158,9 @@
     case SHARED_FUNCTION_INFO_TYPE:
       SharedFunctionInfo::cast(this)->SharedFunctionInfoVerify();
       break;
+    case JS_MESSAGE_OBJECT_TYPE:
+      JSMessageObject::cast(this)->JSMessageObjectVerify();
+      break;

 #define MAKE_STRUCT_CASE(NAME, Name, name) \
   case NAME##_TYPE:                        \
@@ -294,6 +297,19 @@
     VerifyHeapPointer(v);
   }
 }
+
+
+void JSMessageObject::JSMessageObjectVerify() {
+  CHECK(IsJSMessageObject());
+  CHECK(type()->IsString());
+  CHECK(arguments()->IsJSArray());
+  VerifyObjectField(kStartPositionOffset);
+  VerifyObjectField(kEndPositionOffset);
+  VerifyObjectField(kArgumentsOffset);
+  VerifyObjectField(kScriptOffset);
+  VerifyObjectField(kStackTraceOffset);
+  VerifyObjectField(kStackFramesOffset);
+}


 void String::StringVerify() {
=======================================
--- /branches/bleeding_edge/src/objects-inl.h   Thu Jan 27 00:35:39 2011
+++ /branches/bleeding_edge/src/objects-inl.h   Wed Feb  2 05:31:52 2011
@@ -408,7 +408,7 @@

 bool MaybeObject::IsOutOfMemory() {
   return HAS_FAILURE_TAG(this)
-    && Failure::cast(this)->IsOutOfMemoryException();
+      && Failure::cast(this)->IsOutOfMemoryException();
 }


@@ -430,26 +430,26 @@

 bool Object::IsJSObject() {
   return IsHeapObject()
- && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE; + && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
 }


 bool Object::IsJSContextExtensionObject() {
   return IsHeapObject()
-    && (HeapObject::cast(this)->map()->instance_type() ==
-        JS_CONTEXT_EXTENSION_OBJECT_TYPE);
+      && (HeapObject::cast(this)->map()->instance_type() ==
+          JS_CONTEXT_EXTENSION_OBJECT_TYPE);
 }


 bool Object::IsMap() {
   return Object::IsHeapObject()
-    && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
+      && HeapObject::cast(this)->map()->instance_type() == MAP_TYPE;
 }


 bool Object::IsFixedArray() {
   return Object::IsHeapObject()
-    && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
+ && HeapObject::cast(this)->map()->instance_type() == FIXED_ARRAY_TYPE;
 }


@@ -495,19 +495,19 @@

 bool Object::IsCatchContext() {
   return Object::IsHeapObject()
-    && HeapObject::cast(this)->map() == Heap::catch_context_map();
+      && HeapObject::cast(this)->map() == Heap::catch_context_map();
 }


 bool Object::IsGlobalContext() {
   return Object::IsHeapObject()
-    && HeapObject::cast(this)->map() == Heap::global_context_map();
+      && HeapObject::cast(this)->map() == Heap::global_context_map();
 }


 bool Object::IsJSFunction() {
   return Object::IsHeapObject()
-    && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
+ && HeapObject::cast(this)->map()->instance_type() == JS_FUNCTION_TYPE;
 }


@@ -518,7 +518,7 @@

 bool Object::IsCode() {
   return Object::IsHeapObject()
-    && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
+      && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
 }


@@ -544,7 +544,14 @@

 bool Object::IsJSValue() {
   return Object::IsHeapObject()
-    && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
+      && HeapObject::cast(this)->map()->instance_type() == JS_VALUE_TYPE;
+}
+
+
+bool Object::IsJSMessageObject() {
+  return Object::IsHeapObject()
+      && (HeapObject::cast(this)->map()->instance_type() ==
+          JS_MESSAGE_OBJECT_TYPE);
 }


@@ -555,7 +562,7 @@

 bool Object::IsProxy() {
   return Object::IsHeapObject()
-    && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
+      && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
 }


@@ -566,13 +573,13 @@

 bool Object::IsJSArray() {
   return Object::IsHeapObject()
-    && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
+      && HeapObject::cast(this)->map()->instance_type() == JS_ARRAY_TYPE;
 }


 bool Object::IsJSRegExp() {
   return Object::IsHeapObject()
-    && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
+      && HeapObject::cast(this)->map()->instance_type() == JS_REGEXP_TYPE;
 }


@@ -583,7 +590,7 @@

 bool Object::IsHashTable() {
   return Object::IsHeapObject()
-    && HeapObject::cast(this)->map() == Heap::hash_table_map();
+      && HeapObject::cast(this)->map() == Heap::hash_table_map();
 }


@@ -1285,6 +1292,8 @@
       return JSValue::kSize;
     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
       return JSObject::kHeaderSize;
+    case JS_MESSAGE_OBJECT_TYPE:
+      return JSMessageObject::kSize;
     default:
       UNREACHABLE();
       return 0;
@@ -3287,6 +3296,22 @@
   ASSERT(HeapObject::cast(obj)->Size() == JSValue::kSize);
   return reinterpret_cast<JSValue*>(obj);
 }
+
+
+ACCESSORS(JSMessageObject, type, String, kTypeOffset)
+ACCESSORS(JSMessageObject, arguments, JSArray, kArgumentsOffset)
+ACCESSORS(JSMessageObject, script, Object, kScriptOffset)
+ACCESSORS(JSMessageObject, stack_trace, Object, kStackTraceOffset)
+ACCESSORS(JSMessageObject, stack_frames, Object, kStackFramesOffset)
+SMI_ACCESSORS(JSMessageObject, start_position, kStartPositionOffset)
+SMI_ACCESSORS(JSMessageObject, end_position, kEndPositionOffset)
+
+
+JSMessageObject* JSMessageObject::cast(Object* obj) {
+  ASSERT(obj->IsJSMessageObject());
+  ASSERT(HeapObject::cast(obj)->Size() == JSMessageObject::kSize);
+  return reinterpret_cast<JSMessageObject*>(obj);
+}


 INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
=======================================
--- /branches/bleeding_edge/src/objects-printer.cc      Wed Jan 19 12:05:22 2011
+++ /branches/bleeding_edge/src/objects-printer.cc      Wed Feb  2 05:31:52 2011
@@ -151,6 +151,9 @@
     case SHARED_FUNCTION_INFO_TYPE:
       SharedFunctionInfo::cast(this)->SharedFunctionInfoPrint(out);
       break;
+    case JS_MESSAGE_OBJECT_TYPE:
+      JSMessageObject::cast(this)->JSMessageObjectPrint(out);
+      break;
     case JS_GLOBAL_PROPERTY_CELL_TYPE:
       JSGlobalPropertyCell::cast(this)->JSGlobalPropertyCellPrint(out);
       break;
@@ -396,6 +399,7 @@
     case JS_GLOBAL_PROXY_TYPE: return "JS_GLOBAL_PROXY";
     case PROXY_TYPE: return "PROXY";
     case LAST_STRING_TYPE: return "LAST_STRING_TYPE";
+    case JS_MESSAGE_OBJECT_TYPE: return "JS_MESSAGE_OBJECT_TYPE";
 #define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return #NAME;
   STRUCT_LIST(MAKE_STRUCT_CASE)
 #undef MAKE_STRUCT_CASE
@@ -464,6 +468,24 @@
   HeapObject::PrintHeader(out, "ValueObject");
   value()->Print(out);
 }
+
+
+void JSMessageObject::JSMessageObjectPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "JSMessageObject");
+  PrintF(out, " - type: ");
+  type()->ShortPrint(out);
+  PrintF(out, "\n - arguments: ");
+  arguments()->ShortPrint(out);
+  PrintF(out, "\n - start_position: %d", start_position());
+  PrintF(out, "\n - end_position: %d", end_position());
+  PrintF(out, "\n - script: ");
+  script()->ShortPrint(out);
+  PrintF(out, "\n - stack_trace: ");
+  stack_trace()->ShortPrint(out);
+  PrintF(out, "\n - stack_frames: ");
+  stack_frames()->ShortPrint(out);
+  PrintF(out, "\n");
+}


 void String::StringPrint(FILE* out) {
=======================================
--- /branches/bleeding_edge/src/objects-visiting.cc     Tue Dec  7 03:01:02 2010
+++ /branches/bleeding_edge/src/objects-visiting.cc     Wed Feb  2 05:31:52 2011
@@ -104,6 +104,7 @@
     case JS_GLOBAL_PROXY_TYPE:
     case JS_GLOBAL_OBJECT_TYPE:
     case JS_BUILTINS_OBJECT_TYPE:
+    case JS_MESSAGE_OBJECT_TYPE:
       return GetVisitorIdForSize(kVisitJSObject,
                                  kVisitJSObjectGeneric,
                                  instance_size);
=======================================
--- /branches/bleeding_edge/src/objects.cc      Tue Feb  1 12:08:01 2011
+++ /branches/bleeding_edge/src/objects.cc      Wed Feb  2 05:31:52 2011
@@ -979,6 +979,9 @@
     case SHARED_FUNCTION_INFO_TYPE:
       accumulator->Add("<SharedFunctionInfo>");
       break;
+    case JS_MESSAGE_OBJECT_TYPE:
+      accumulator->Add("<JSMessageObject>");
+      break;
 #define MAKE_STRUCT_CASE(NAME, Name, name) \
   case NAME##_TYPE:                        \
     accumulator->Put('<');                 \
@@ -1069,6 +1072,7 @@
     case JS_GLOBAL_PROXY_TYPE:
     case JS_GLOBAL_OBJECT_TYPE:
     case JS_BUILTINS_OBJECT_TYPE:
+    case JS_MESSAGE_OBJECT_TYPE:
       JSObject::BodyDescriptor::IterateBody(this, object_size, v);
       break;
     case JS_FUNCTION_TYPE:
=======================================
--- /branches/bleeding_edge/src/objects.h       Wed Jan 19 12:05:22 2011
+++ /branches/bleeding_edge/src/objects.h       Wed Feb  2 05:31:52 2011
@@ -54,7 +54,8 @@
 //           - JSGlobalObject
 //           - JSBuiltinsObject
 //         - JSGlobalProxy
-//        - JSValue
+//         - JSValue
+//         - JSMessageObject
 //       - ByteArray
 //       - PixelArray
 //       - ExternalArray
@@ -288,6 +289,8 @@
V(FIXED_ARRAY_TYPE) \ V(SHARED_FUNCTION_INFO_TYPE) \ \ + V(JS_MESSAGE_OBJECT_TYPE) \ + \ V(JS_VALUE_TYPE) \ V(JS_OBJECT_TYPE) \ V(JS_CONTEXT_EXTENSION_OBJECT_TYPE) \
@@ -518,6 +521,8 @@
   FIXED_ARRAY_TYPE,
   SHARED_FUNCTION_INFO_TYPE,

+  JS_MESSAGE_OBJECT_TYPE,
+
   JS_VALUE_TYPE,  // FIRST_JS_OBJECT_TYPE
   JS_OBJECT_TYPE,
   JS_CONTEXT_EXTENSION_OBJECT_TYPE,
@@ -675,6 +680,7 @@
   V(Oddball)                                   \
   V(SharedFunctionInfo)                        \
   V(JSValue)                                   \
+  V(JSMessageObject)                           \
   V(StringWrapper)                             \
   V(Proxy)                                     \
   V(Boolean)                                   \
@@ -4696,6 +4702,68 @@
   DISALLOW_IMPLICIT_CONSTRUCTORS(JSValue);
 };

+
+// Representation of message objects used for error reporting through
+// the API. The messages are formatted in JavaScript so this object is
+// a real JavaScript object. The information used for formatting the
+// error messages are not directly accessible from JavaScript to
+// prevent leaking information to user code called during error
+// formatting.
+class JSMessageObject: public JSObject {
+ public:
+  // [type]: the type of error message.
+  DECL_ACCESSORS(type, String)
+
+  // [arguments]: the arguments for formatting the error message.
+  DECL_ACCESSORS(arguments, JSArray)
+
+  // [script]: the script from which the error message originated.
+  DECL_ACCESSORS(script, Object)
+
+  // [stack_trace]: the stack trace for this error message.
+  DECL_ACCESSORS(stack_trace, Object)
+
+  // [stack_frames]: an array of stack frames for this error object.
+  DECL_ACCESSORS(stack_frames, Object)
+
+ // [start_position]: the start position in the script for the error message.
+  inline int start_position();
+  inline void set_start_position(int value);
+
+  // [end_position]: the end position in the script for the error message.
+  inline int end_position();
+  inline void set_end_position(int value);
+
+  // Casting.
+  static inline JSMessageObject* cast(Object* obj);
+
+  // Dispatched behavior.
+#ifdef OBJECT_PRINT
+  inline void JSMessageObjectPrint() {
+    JSMessageObjectPrint(stdout);
+  }
+  void JSMessageObjectPrint(FILE* out);
+#endif
+#ifdef DEBUG
+  void JSMessageObjectVerify();
+#endif
+
+  // Layout description.
+  static const int kTypeOffset = JSObject::kHeaderSize;
+  static const int kArgumentsOffset = kTypeOffset + kPointerSize;
+  static const int kScriptOffset = kArgumentsOffset + kPointerSize;
+  static const int kStackTraceOffset = kScriptOffset + kPointerSize;
+  static const int kStackFramesOffset = kStackTraceOffset + kPointerSize;
+ static const int kStartPositionOffset = kStackFramesOffset + kPointerSize; + static const int kEndPositionOffset = kStartPositionOffset + kPointerSize;
+  static const int kSize = kEndPositionOffset + kPointerSize;
+
+  typedef FixedBodyDescriptor<HeapObject::kMapOffset,
+                              kStackFramesOffset + kPointerSize,
+                              kSize> BodyDescriptor;
+};
+
+
 // Regular expressions
 // The regular expression holds a single reference to a FixedArray in
 // the kDataOffset field.
=======================================
--- /branches/bleeding_edge/src/runtime.cc      Tue Feb  1 12:08:01 2011
+++ /branches/bleeding_edge/src/runtime.cc      Wed Feb  2 05:31:52 2011
@@ -10747,6 +10747,45 @@

   return *value;
 }
+
+
+static MaybeObject* Runtime_NewMessageObject(Arguments args) {
+  HandleScope scope;
+  CONVERT_ARG_CHECKED(String, type, 0);
+  CONVERT_ARG_CHECKED(JSArray, arguments, 1);
+  return *Factory::NewJSMessageObject(type,
+                                      arguments,
+                                      0,
+                                      0,
+                                      Factory::undefined_value(),
+                                      Factory::undefined_value(),
+                                      Factory::undefined_value());
+}
+
+
+static MaybeObject* Runtime_MessageGetType(Arguments args) {
+  CONVERT_CHECKED(JSMessageObject, message, args[0]);
+  return message->type();
+}
+
+
+static MaybeObject* Runtime_MessageGetArguments(Arguments args) {
+  CONVERT_CHECKED(JSMessageObject, message, args[0]);
+  return message->arguments();
+}
+
+
+static MaybeObject* Runtime_MessageGetStartPosition(Arguments args) {
+  CONVERT_CHECKED(JSMessageObject, message, args[0]);
+  return Smi::FromInt(message->start_position());
+}
+
+
+static MaybeObject* Runtime_MessageGetScript(Arguments args) {
+  CONVERT_CHECKED(JSMessageObject, message, args[0]);
+  return message->script();
+}
+

 #ifdef DEBUG
 // ListNatives is ONLY used by the fuzz-natives.js in debug mode
=======================================
--- /branches/bleeding_edge/src/runtime.h       Mon Jan 24 06:03:30 2011
+++ /branches/bleeding_edge/src/runtime.h       Wed Feb  2 05:31:52 2011
@@ -310,6 +310,13 @@
   /* Cache suport */ \
   F(GetFromCache, 2, 1) \
   \
+  /* Message objects */ \
+  F(NewMessageObject, 2, 1) \
+  F(MessageGetType, 1, 1) \
+  F(MessageGetArguments, 1, 1) \
+  F(MessageGetStartPosition, 1, 1) \
+  F(MessageGetScript, 1, 1) \
+  \
   /* Pseudo functions - handled as macros by parser */ \
   F(IS_VAR, 1, 1)

=======================================
--- /branches/bleeding_edge/test/cctest/test-api.cc     Wed Feb  2 00:14:06 2011
+++ /branches/bleeding_edge/test/cctest/test-api.cc     Wed Feb  2 05:31:52 2011
@@ -2385,6 +2385,11 @@
   Local<ObjectTemplate> templ = ObjectTemplate::New();
   templ->Set(v8_str("fail"), v8::FunctionTemplate::New(Fail));
   LocalContext context(NULL, templ);
+  CompileRun("asdf;");
+  CompileRun("var limit = {};"
+             "limit.valueOf = fail;"
+             "Error.stackTraceLimit = limit;");
+  CompileRun("asdf");
   CompileRun("Array.prototype.pop = fail;");
   CompileRun("Object.prototype.hasOwnProperty = fail;");
CompileRun("Object.prototype.toString = function f() { return 'Yikes'; }");

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to