Index: src/top.cc |
=================================================================== |
--- src/top.cc (revision 4556) |
+++ src/top.cc (working copy) |
@@ -337,7 +337,7 @@ |
static StringStream* incomplete_message = NULL; |
-Handle<String> Top::StackTrace() { |
+Handle<String> Top::StackTraceString() { |
if (stack_trace_nesting_level == 0) { |
stack_trace_nesting_level++; |
HeapStringAllocator allocator; |
@@ -365,6 +365,90 @@ |
} |
+Local<StackTrace> Top::CaptureCurrentStackTrace( |
+ int frame_limit, StackTrace::StackTraceOptions options) { |
+ v8::HandleScope scope; |
+ // Ensure no negative values. |
+ int limit = Max(frame_limit, 0); |
+ Handle<JSArray> stackTrace = Factory::NewJSArray(frame_limit); |
+ FixedArray* frames = FixedArray::cast(stackTrace->elements()); |
+ |
+ Handle<String> column_key = Factory::LookupAsciiSymbol("column"); |
+ Handle<String> line_key = Factory::LookupAsciiSymbol("lineNumber"); |
+ Handle<String> script_key = Factory::LookupAsciiSymbol("scriptName"); |
+ Handle<String> function_key = Factory::LookupAsciiSymbol("functionName"); |
+ Handle<String> eval_key = Factory::LookupAsciiSymbol("isEval"); |
+ Handle<String> constructor_key = Factory::LookupAsciiSymbol("isConstructor"); |
+ |
+ StackTraceFrameIterator it; |
+ int frames_seen = 0; |
+ while (!it.done() && (frames_seen < limit)) { |
+ // Create a JSObject to hold the information for the StackFrame. |
+ Handle<JSObject> stackFrame = Factory::NewJSObject(object_function()); |
+ |
+ JavaScriptFrame* frame = it.frame(); |
+ JSFunction* fun(JSFunction::cast(frame->function())); |
+ Script* script = Script::cast(fun->shared()->script()); |
+ |
+ if (options & StackTrace::kLineNumber) { |
+ int script_line_offset = script->line_offset()->value(); |
+ int position = frame->code()->SourcePosition(frame->pc()); |
+ int line_number = GetScriptLineNumber(Handle<Script>(script), position); |
+ |
+ if (options & StackTrace::kColumnOffset) { |
+ Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends())); |
+ int start = (line_number == 0) ? |
+ 0 : Smi::cast(line_ends->get(line_number - 1))->value() + 1; |
+ int column_offset = position - start; |
+ if (line_number == script_line_offset) { |
+ // For the case where the code is on the same line as the script tag. |
+ column_offset += script_line_offset; |
+ } |
+ SetProperty(stackFrame, column_key, |
+ Handle<Smi>(Smi::FromInt(column_offset + 1)), NONE); |
+ } |
+ // Adjust the line_number by the offset in the parent resource. |
+ line_number += script_line_offset; |
+ SetProperty(stackFrame, line_key, |
+ Handle<Smi>(Smi::FromInt(line_number + 1)), NONE); |
+ } |
+ |
+ if (options & StackTrace::kScriptName) { |
+ Handle<Object> script_name(script->name()); |
+ SetProperty(stackFrame, script_key, script_name, NONE); |
+ } |
+ |
+ if (options & StackTrace::kFunctionName) { |
+ Handle<Object> fun_name(fun->shared()->name()); |
+ if (!fun_name->IsString()) { |
+ fun_name = Handle<Object>(fun->shared()->inferred_name()); |
+ } |
+ SetProperty(stackFrame, function_key, fun_name, NONE); |
+ } |
+ |
+ if (options & StackTrace::kIsEval) { |
+ int type = Smi::cast(script->compilation_type())->value(); |
+ Handle<Object> is_eval = (type == Script::COMPILATION_TYPE_EVAL) ? |
+ Factory::true_value() : Factory::false_value(); |
+ SetProperty(stackFrame, eval_key, is_eval, NONE); |
+ } |
+ |
+ if (options & StackTrace::kIsConstructor) { |
+ Handle<Object> is_constructor = (frame->IsConstructor()) ? |
+ Factory::true_value() : Factory::false_value(); |
+ SetProperty(stackFrame, constructor_key, is_constructor, NONE); |
+ } |
+ |
+ frames->set(frames_seen, *stackFrame); |
+ frames_seen++; |
+ it.Advance(); |
+ } |
+ |
+ stackTrace->set_length(Smi::FromInt(frames_seen)); |
+ return scope.Close(Utils::StackTraceToLocal(stackTrace)); |
+} |
+ |
+ |
void Top::PrintStack() { |
if (stack_trace_nesting_level == 0) { |
stack_trace_nesting_level++; |
@@ -786,7 +870,7 @@ |
// traces while the bootstrapper is active since the infrastructure |
// may not have been properly initialized. |
Handle<String> stack_trace; |
- if (FLAG_trace_exception) stack_trace = StackTrace(); |
+ if (FLAG_trace_exception) stack_trace = StackTraceString(); |
message_obj = MessageHandler::MakeMessageObject("uncaught_exception", |
location, HandleVector<Object>(&exception_handle, 1), stack_trace); |
} |