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;
}
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));
}
}
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));
}
}
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);
ON_BAILOUT("v8::Message::GetLineNumber()", return kNoLineNumberInfo);
ENTER_V8;
HandleScope scope;
+
EXCEPTION_PREAMBLE();
i::Handle<i::Object> result = CallV8HeapFunction("GetLineNumber",
Utils::OpenHandle(this),
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();
}
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();
}
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);
}
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);
}
}
+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),
SharedFunctionInfo);
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,
}
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;
}
}
+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.
static inline bool Between(uint32_t character, uint32_t from, uint32_t to) {
// This makes uses of the the unsigned wraparound.
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) \
// 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.
}
-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();
+ script_handle = GetScriptWrapper(loc->script());
}
- 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);
+
+ 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;
}
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);
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++) {
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;
}
// 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();
// 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;
}
// 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));
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);
});
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)
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: \
}
+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() {
CHECK(IsString());
CHECK(length() >= 0 && length() <= Smi::kMaxValue);
bool MaybeObject::IsOutOfMemory() {
return HAS_FAILURE_TAG(this)
- && Failure::cast(this)->IsOutOfMemoryException();
+ && Failure::cast(this)->IsOutOfMemoryException();
}
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;
}
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;
}
bool Object::IsCode() {
return Object::IsHeapObject()
- && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
+ && HeapObject::cast(this)->map()->instance_type() == CODE_TYPE;
}
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);
}
bool Object::IsProxy() {
return Object::IsHeapObject()
- && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
+ && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
}
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;
}
bool Object::IsHashTable() {
return Object::IsHeapObject()
- && HeapObject::cast(this)->map() == Heap::hash_table_map();
+ && HeapObject::cast(this)->map() == Heap::hash_table_map();
}
return JSValue::kSize;
case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
return JSObject::kHeaderSize;
+ case JS_MESSAGE_OBJECT_TYPE:
+ return JSMessageObject::kSize;
default:
UNREACHABLE();
return 0;
}
+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)
ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
ACCESSORS(Code, deoptimization_data, FixedArray, kDeoptimizationDataOffset)
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;
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
}
+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) {
if (StringShape(this).IsSymbol()) {
PrintF(out, "#");
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);
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('<'); \
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:
// - JSGlobalObject
// - JSBuiltinsObject
// - JSGlobalProxy
-// - JSValue
+// - JSValue
+// - JSMessageObject
// - ByteArray
// - PixelArray
// - ExternalArray
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) \
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,
V(Oddball) \
V(SharedFunctionInfo) \
V(JSValue) \
+ V(JSMessageObject) \
V(StringWrapper) \
V(Proxy) \
V(Boolean) \
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.
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
// Exclude the code in release mode.
/* 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)
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'; }");