375
380
int limit = Max(frame_limit, 0);
376
381
Handle<JSArray> stack_trace = Factory::NewJSArray(frame_limit);
378
Handle<String> column_key = Factory::LookupAsciiSymbol("column");
379
Handle<String> line_key = Factory::LookupAsciiSymbol("lineNumber");
380
Handle<String> script_key = Factory::LookupAsciiSymbol("scriptName");
381
Handle<String> function_key = Factory::LookupAsciiSymbol("functionName");
382
Handle<String> eval_key = Factory::LookupAsciiSymbol("isEval");
383
Handle<String> constructor_key = Factory::LookupAsciiSymbol("isConstructor");
383
Handle<String> column_key = Factory::LookupAsciiSymbol("column");
384
Handle<String> line_key = Factory::LookupAsciiSymbol("lineNumber");
385
Handle<String> script_key = Factory::LookupAsciiSymbol("scriptName");
386
Handle<String> name_or_source_url_key =
387
Factory::LookupAsciiSymbol("nameOrSourceURL");
388
Handle<String> script_name_or_source_url_key =
389
Factory::LookupAsciiSymbol("scriptNameOrSourceURL");
390
Handle<String> function_key = Factory::LookupAsciiSymbol("functionName");
391
Handle<String> eval_key = Factory::LookupAsciiSymbol("isEval");
392
Handle<String> constructor_key = Factory::LookupAsciiSymbol("isConstructor");
385
394
StackTraceFrameIterator it;
386
395
int frames_seen = 0;
387
396
while (!it.done() && (frames_seen < limit)) {
388
// Create a JSObject to hold the information for the StackFrame.
389
Handle<JSObject> stackFrame = Factory::NewJSObject(object_function());
391
397
JavaScriptFrame* frame = it.frame();
392
JSFunction* fun(JSFunction::cast(frame->function()));
393
Script* script = Script::cast(fun->shared()->script());
395
if (options & StackTrace::kLineNumber) {
396
int script_line_offset = script->line_offset()->value();
397
int position = frame->code()->SourcePosition(frame->pc());
398
int line_number = GetScriptLineNumber(Handle<Script>(script), position);
399
// line_number is already shifted by the script_line_offset.
400
int relative_line_number = line_number - script_line_offset;
401
if (options & StackTrace::kColumnOffset && relative_line_number >= 0) {
402
Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()));
403
int start = (relative_line_number == 0) ? 0 :
404
Smi::cast(line_ends->get(relative_line_number - 1))->value() + 1;
405
int column_offset = position - start;
406
if (relative_line_number == 0) {
407
// For the case where the code is on the same line as the script tag.
408
column_offset += script->column_offset()->value();
410
SetProperty(stackFrame, column_key,
411
Handle<Smi>(Smi::FromInt(column_offset + 1)), NONE);
413
SetProperty(stackFrame, line_key,
414
Handle<Smi>(Smi::FromInt(line_number + 1)), NONE);
417
if (options & StackTrace::kScriptName) {
418
Handle<Object> script_name(script->name());
419
SetProperty(stackFrame, script_key, script_name, NONE);
422
if (options & StackTrace::kFunctionName) {
423
Handle<Object> fun_name(fun->shared()->name());
424
if (fun_name->ToBoolean()->IsFalse()) {
425
fun_name = Handle<Object>(fun->shared()->inferred_name());
427
SetProperty(stackFrame, function_key, fun_name, NONE);
430
if (options & StackTrace::kIsEval) {
431
int type = Smi::cast(script->compilation_type())->value();
432
Handle<Object> is_eval = (type == Script::COMPILATION_TYPE_EVAL) ?
433
Factory::true_value() : Factory::false_value();
434
SetProperty(stackFrame, eval_key, is_eval, NONE);
437
if (options & StackTrace::kIsConstructor) {
438
Handle<Object> is_constructor = (frame->IsConstructor()) ?
439
Factory::true_value() : Factory::false_value();
440
SetProperty(stackFrame, constructor_key, is_constructor, NONE);
443
FixedArray::cast(stack_trace->elements())->set(frames_seen, *stackFrame);
399
List<FrameSummary> frames(3); // Max 2 levels of inlining.
400
frame->Summarize(&frames);
401
for (int i = frames.length() - 1; i >= 0 && frames_seen < limit; i--) {
402
// Create a JSObject to hold the information for the StackFrame.
403
Handle<JSObject> stackFrame = Factory::NewJSObject(object_function());
405
Handle<JSFunction> fun = frames[i].function();
406
Handle<Script> script(Script::cast(fun->shared()->script()));
408
if (options & StackTrace::kLineNumber) {
409
int script_line_offset = script->line_offset()->value();
410
int position = frames[i].code()->SourcePosition(frames[i].pc());
411
int line_number = GetScriptLineNumber(script, position);
412
// line_number is already shifted by the script_line_offset.
413
int relative_line_number = line_number - script_line_offset;
414
if (options & StackTrace::kColumnOffset && relative_line_number >= 0) {
415
Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()));
416
int start = (relative_line_number == 0) ? 0 :
417
Smi::cast(line_ends->get(relative_line_number - 1))->value() + 1;
418
int column_offset = position - start;
419
if (relative_line_number == 0) {
420
// For the case where the code is on the same line as the script
422
column_offset += script->column_offset()->value();
424
SetLocalPropertyNoThrow(stackFrame, column_key,
425
Handle<Smi>(Smi::FromInt(column_offset + 1)));
427
SetLocalPropertyNoThrow(stackFrame, line_key,
428
Handle<Smi>(Smi::FromInt(line_number + 1)));
431
if (options & StackTrace::kScriptName) {
432
Handle<Object> script_name(script->name());
433
SetLocalPropertyNoThrow(stackFrame, script_key, script_name);
436
if (options & StackTrace::kScriptNameOrSourceURL) {
437
Handle<Object> script_name(script->name());
438
Handle<JSValue> script_wrapper = GetScriptWrapper(script);
439
Handle<Object> property = GetProperty(script_wrapper,
440
name_or_source_url_key);
441
ASSERT(property->IsJSFunction());
442
Handle<JSFunction> method = Handle<JSFunction>::cast(property);
443
bool caught_exception;
444
Handle<Object> result = Execution::TryCall(method, script_wrapper, 0,
445
NULL, &caught_exception);
446
if (caught_exception) {
447
result = Factory::undefined_value();
449
SetLocalPropertyNoThrow(stackFrame, script_name_or_source_url_key,
453
if (options & StackTrace::kFunctionName) {
454
Handle<Object> fun_name(fun->shared()->name());
455
if (fun_name->ToBoolean()->IsFalse()) {
456
fun_name = Handle<Object>(fun->shared()->inferred_name());
458
SetLocalPropertyNoThrow(stackFrame, function_key, fun_name);
461
if (options & StackTrace::kIsEval) {
462
int type = Smi::cast(script->compilation_type())->value();
463
Handle<Object> is_eval = (type == Script::COMPILATION_TYPE_EVAL) ?
464
Factory::true_value() : Factory::false_value();
465
SetLocalPropertyNoThrow(stackFrame, eval_key, is_eval);
468
if (options & StackTrace::kIsConstructor) {
469
Handle<Object> is_constructor = (frames[i].is_constructor()) ?
470
Factory::true_value() : Factory::false_value();
471
SetLocalPropertyNoThrow(stackFrame, constructor_key, is_constructor);
474
FixedArray::cast(stack_trace->elements())->set(frames_seen, *stackFrame);
808
void Top::DoThrow(Object* exception,
847
void Top::DoThrow(MaybeObject* exception,
809
848
MessageLocation* location,
810
849
const char* message) {
811
850
ASSERT(!has_pending_exception());
813
852
HandleScope scope;
814
Handle<Object> exception_handle(exception);
853
Object* exception_object = Smi::FromInt(0);
854
bool is_object = exception->ToObject(&exception_object);
855
Handle<Object> exception_handle(exception_object);
816
857
// Determine reporting and whether the exception is caught externally.
817
bool is_caught_externally = false;
818
bool is_out_of_memory = exception == Failure::OutOfMemoryException();
819
bool is_termination_exception = exception == Heap::termination_exception();
820
bool catchable_by_javascript = !is_termination_exception && !is_out_of_memory;
821
bool should_return_exception =
822
ShouldReturnException(&is_caught_externally, catchable_by_javascript);
823
bool report_exception = catchable_by_javascript && should_return_exception;
858
bool catchable_by_javascript = is_catchable_by_javascript(exception);
859
// Only real objects can be caught by JS.
860
ASSERT(!catchable_by_javascript || is_object);
861
bool can_be_caught_externally = false;
862
bool should_report_exception =
863
ShouldReportException(&can_be_caught_externally, catchable_by_javascript);
864
bool report_exception = catchable_by_javascript && should_report_exception;
825
866
#ifdef ENABLE_DEBUGGER_SUPPORT
826
867
// Notify debugger of exception.
874
if (is_caught_externally) {
875
thread_local_.catcher_ = thread_local_.TryCatchHandler();
916
// Do not forget to clean catcher_ if currently thrown exception cannot
917
// be caught. If necessary, ReThrow will update the catcher.
918
thread_local_.catcher_ = can_be_caught_externally ?
919
try_catch_handler() : NULL;
878
921
// NOTE: Notifying the debugger or generating the message
879
922
// may have caused new exceptions. For now, we just ignore
880
923
// that and set the pending exception to the original one.
881
set_pending_exception(*exception_handle);
925
set_pending_exception(*exception_handle);
927
// Failures are not on the heap so they neither need nor work with handles.
928
ASSERT(exception_handle->IsFailure());
929
set_pending_exception(exception);
934
bool Top::IsExternallyCaught() {
935
ASSERT(has_pending_exception());
937
if ((thread_local_.catcher_ == NULL) ||
938
(try_catch_handler() != thread_local_.catcher_)) {
939
// When throwing the exception, we found no v8::TryCatch
940
// which should care about this exception.
944
if (!is_catchable_by_javascript(pending_exception())) {
948
// Get the address of the external handler so we can compare the address to
949
// determine which one is closer to the top of the stack.
950
Address external_handler_address = thread_local_.try_catch_handler_address();
951
ASSERT(external_handler_address != NULL);
953
// The exception has been externally caught if and only if there is
954
// an external handler which is on top of the top-most try-finally
956
// There should be no try-catch blocks as they would prohibit us from
957
// finding external catcher in the first place (see catcher_ check above).
959
// Note, that finally clause would rethrow an exception unless it's
960
// aborted by jumps in control flow like return, break, etc. and we'll
961
// have another chances to set proper v8::TryCatch.
962
StackHandler* handler =
963
StackHandler::FromAddress(Top::handler(Top::GetCurrentThread()));
964
while (handler != NULL && handler->address() < external_handler_address) {
965
ASSERT(!handler->is_try_catch());
966
if (handler->is_try_finally()) return false;
968
handler = handler->next();
885
975
void Top::ReportPendingMessages() {
886
976
ASSERT(has_pending_exception());
887
setup_external_caught();
888
977
// If the pending exception is OutOfMemoryException set out_of_memory in
889
978
// the global context. Note: We have to mark the global context here
890
979
// since the GenerateThrowOutOfMemory stub cannot make a RuntimeCall to
892
bool external_caught = thread_local_.external_caught_exception_;
981
bool external_caught = IsExternallyCaught();
982
thread_local_.external_caught_exception_ = external_caught;
893
983
HandleScope scope;
894
984
if (thread_local_.pending_exception_ == Failure::OutOfMemoryException()) {
895
985
context()->mark_out_of_memory();
896
986
} else if (thread_local_.pending_exception_ ==
897
987
Heap::termination_exception()) {
898
988
if (external_caught) {
899
thread_local_.TryCatchHandler()->can_continue_ = false;
900
thread_local_.TryCatchHandler()->exception_ = Heap::null_value();
989
try_catch_handler()->can_continue_ = false;
990
try_catch_handler()->exception_ = Heap::null_value();
903
Handle<Object> exception(pending_exception());
993
// At this point all non-object (failure) exceptions have
994
// been dealt with so this shouldn't fail.
995
Object* pending_exception_object = pending_exception()->ToObjectUnchecked();
996
Handle<Object> exception(pending_exception_object);
904
997
thread_local_.external_caught_exception_ = false;
905
998
if (external_caught) {
906
thread_local_.TryCatchHandler()->can_continue_ = true;
907
thread_local_.TryCatchHandler()->exception_ =
908
thread_local_.pending_exception_;
999
try_catch_handler()->can_continue_ = true;
1000
try_catch_handler()->exception_ = thread_local_.pending_exception_;
909
1001
if (!thread_local_.pending_message_obj_->IsTheHole()) {
910
1002
try_catch_handler()->message_ = thread_local_.pending_message_obj_;