Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(55)

Side by Side Diff: src/messages.cc

Issue 2191293002: Move FormatStackTrace to C++ (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Remove unneeded code from messages.js Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/messages.h" 5 #include "src/messages.h"
6 6
7 #include <memory> 7 #include <memory>
8 8
9 #include "src/api.h" 9 #include "src/api.h"
10 #include "src/bootstrapper.h"
11 #include "src/execution.h" 10 #include "src/execution.h"
12 #include "src/isolate-inl.h" 11 #include "src/isolate-inl.h"
13 #include "src/keys.h" 12 #include "src/keys.h"
14 #include "src/string-builder.h" 13 #include "src/string-builder.h"
15 #include "src/wasm/wasm-module.h" 14 #include "src/wasm/wasm-module.h"
16 15
17 namespace v8 { 16 namespace v8 {
18 namespace internal { 17 namespace internal {
19 18
20 MessageLocation::MessageLocation(Handle<Script> script, int start_pos, 19 MessageLocation::MessageLocation(Handle<Script> script, int start_pos,
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 // Return null in case of duplicates to avoid confusion. 296 // Return null in case of duplicates to avoid confusion.
298 if (!result.is_null()) return isolate_->factory()->null_value(); 297 if (!result.is_null()) return isolate_->factory()->null_value();
299 result = inner_scope.CloseAndEscape(name_key); 298 result = inner_scope.CloseAndEscape(name_key);
300 } 299 }
301 } 300 }
302 301
303 if (!result.is_null()) return outer_scope.CloseAndEscape(result); 302 if (!result.is_null()) return outer_scope.CloseAndEscape(result);
304 return isolate_->factory()->null_value(); 303 return isolate_->factory()->null_value();
305 } 304 }
306 305
306 Handle<Object> CallSite::GetTypeName() {
307 // TODO(jgruber): Check for strict/constructor here as in
308 // CallSitePrototypeGetThis.
309
310 if (receiver_->IsNull(isolate_) || receiver_->IsUndefined(isolate_))
311 return isolate_->factory()->null_value();
312
313 if (receiver_->IsJSProxy()) return isolate_->factory()->Proxy_string();
314
315 Handle<JSReceiver> receiver_object =
316 Object::ToObject(isolate_, receiver_).ToHandleChecked();
317 return JSReceiver::GetConstructorName(receiver_object);
318 }
319
320 namespace {
321
322 Object* EvalFromFunctionName(Isolate* isolate, Handle<Script> script) {
323 if (script->eval_from_shared()->IsUndefined(isolate))
324 return *isolate->factory()->undefined_value();
325
326 Handle<SharedFunctionInfo> shared(
327 SharedFunctionInfo::cast(script->eval_from_shared()));
328 // Find the name of the function calling eval.
329 if (shared->name()->BooleanValue()) {
330 return shared->name();
331 }
332
333 return shared->inferred_name();
334 }
335
336 Object* EvalFromScript(Isolate* isolate, Handle<Script> script) {
337 if (script->eval_from_shared()->IsUndefined(isolate))
338 return *isolate->factory()->undefined_value();
339
340 Handle<SharedFunctionInfo> eval_from_shared(
341 SharedFunctionInfo::cast(script->eval_from_shared()));
342 return eval_from_shared->script()->IsScript()
343 ? eval_from_shared->script()
344 : *isolate->factory()->undefined_value();
345 }
346
347 MaybeHandle<String> FormatEvalOrigin(Isolate* isolate, Handle<Script> script) {
348 Handle<Object> sourceURL = Script::GetNameOrSourceURL(script);
349 if (!sourceURL->IsUndefined(isolate)) {
350 DCHECK(sourceURL->IsString());
351 return Handle<String>::cast(sourceURL);
352 }
353
354 IncrementalStringBuilder builder(isolate);
355 builder.AppendCString("eval at ");
356
357 Handle<Object> eval_from_function_name =
358 handle(EvalFromFunctionName(isolate, script), isolate);
359 if (eval_from_function_name->BooleanValue()) {
360 Handle<String> str;
361 ASSIGN_RETURN_ON_EXCEPTION(
362 isolate, str, Object::ToString(isolate, eval_from_function_name),
363 String);
364 builder.AppendString(str);
365 } else {
366 builder.AppendCString("<anonymous>");
367 }
368
369 Handle<Object> eval_from_script_obj =
370 handle(EvalFromScript(isolate, script), isolate);
371 if (eval_from_script_obj->IsScript()) {
372 Handle<Script> eval_from_script =
373 Handle<Script>::cast(eval_from_script_obj);
374 builder.AppendCString(" (");
375 if (eval_from_script->compilation_type() == Script::COMPILATION_TYPE_EVAL) {
376 // Eval script originated from another eval.
377 Handle<String> str;
378 ASSIGN_RETURN_ON_EXCEPTION(
379 isolate, str, FormatEvalOrigin(isolate, eval_from_script), String);
380 builder.AppendString(str);
381 } else {
382 DCHECK(eval_from_script->compilation_type() !=
383 Script::COMPILATION_TYPE_EVAL);
384 // eval script originated from "real" source.
385 Handle<Object> name_obj = handle(eval_from_script->name(), isolate);
386 if (eval_from_script->name()->IsString()) {
387 builder.AppendString(Handle<String>::cast(name_obj));
388
389 Script::PositionInfo info;
390 if (eval_from_script->GetPositionInfo(script->GetEvalPosition(), &info,
391 Script::NO_OFFSET)) {
392 builder.AppendCString(":");
393
394 Handle<String> str = isolate->factory()->NumberToString(
395 handle(Smi::FromInt(info.line + 1), isolate));
396 builder.AppendString(str);
397
398 builder.AppendCString(":");
399
400 str = isolate->factory()->NumberToString(
401 handle(Smi::FromInt(info.column + 1), isolate));
402 builder.AppendString(str);
403 }
404 } else {
405 DCHECK(!eval_from_script->name()->IsString());
406 builder.AppendCString("unknown source");
407 }
408 }
409 builder.AppendCString(")");
410 }
411
412 Handle<String> result;
413 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, builder.Finish(), String);
414 return result;
415 }
416
417 } // namespace
418
419 Handle<Object> CallSite::GetEvalOrigin() {
420 if (IsWasm()) return isolate_->factory()->undefined_value();
421 DCHECK(IsJavaScript());
422
423 Handle<Object> script = handle(fun_->shared()->script(), isolate_);
424 if (!script->IsScript()) return isolate_->factory()->undefined_value();
425
426 return FormatEvalOrigin(isolate_, Handle<Script>::cast(script))
427 .ToHandleChecked();
428 }
307 429
308 int CallSite::GetLineNumber() { 430 int CallSite::GetLineNumber() {
309 if (pos_ >= 0 && IsJavaScript()) { 431 if (pos_ >= 0 && IsJavaScript()) {
310 Handle<Object> script_obj(fun_->shared()->script(), isolate_); 432 Handle<Object> script_obj(fun_->shared()->script(), isolate_);
311 if (script_obj->IsScript()) { 433 if (script_obj->IsScript()) {
312 Handle<Script> script = Handle<Script>::cast(script_obj); 434 Handle<Script> script = Handle<Script>::cast(script_obj);
313 return Script::GetLineNumber(script, pos_) + 1; 435 return Script::GetLineNumber(script, pos_) + 1;
314 } 436 }
315 } 437 }
316 return -1; 438 return -1;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 // receiver. 480 // receiver.
359 Object* ctor_symbol = isolate_->heap()->call_site_constructor_symbol(); 481 Object* ctor_symbol = isolate_->heap()->call_site_constructor_symbol();
360 if (*receiver_ == ctor_symbol) return true; 482 if (*receiver_ == ctor_symbol) return true;
361 if (!IsJavaScript() || !receiver_->IsJSObject()) return false; 483 if (!IsJavaScript() || !receiver_->IsJSObject()) return false;
362 Handle<Object> constructor = 484 Handle<Object> constructor =
363 JSReceiver::GetDataProperty(Handle<JSObject>::cast(receiver_), 485 JSReceiver::GetDataProperty(Handle<JSObject>::cast(receiver_),
364 isolate_->factory()->constructor_string()); 486 isolate_->factory()->constructor_string());
365 return constructor.is_identical_to(fun_); 487 return constructor.is_identical_to(fun_);
366 } 488 }
367 489
490 namespace {
491
492 // Convert the raw frames as written by Isolate::CaptureSimpleStackTrace into
493 // a vector of JS CallSite objects.
494 MaybeHandle<FixedArray> GetStackFrames(Isolate* isolate,
495 Handle<Object> raw_stack) {
496 DCHECK(raw_stack->IsJSArray());
497 Handle<JSArray> raw_stack_array = Handle<JSArray>::cast(raw_stack);
498
499 DCHECK(raw_stack_array->elements()->IsFixedArray());
500 Handle<FixedArray> raw_stack_elements =
501 handle(FixedArray::cast(raw_stack_array->elements()), isolate);
502
503 const int raw_stack_len = raw_stack_elements->length();
504 DCHECK(raw_stack_len % 4 == 1); // Multiples of 4 plus sloppy frames count.
505 const int frame_count = (raw_stack_len - 1) / 4;
506
507 Handle<Object> sloppy_frames_obj =
508 FixedArray::get(*raw_stack_elements, 0, isolate);
509 int sloppy_frames = Handle<Smi>::cast(sloppy_frames_obj)->value();
510
511 Handle<JSFunction> callsite_ctor =
512 handle(isolate->native_context()->callsite_function(), isolate);
513
514 int dst_ix = 0;
515 Handle<FixedArray> frames = isolate->factory()->NewFixedArray(frame_count);
516 for (int i = 1; i < raw_stack_len; i += 4) {
Yang 2016/08/01 06:49:18 I wonder whether allocating CallSite objects is mo
jgruber 2016/08/01 10:52:55 Acknowledged.
517 Handle<Object> recv = FixedArray::get(*raw_stack_elements, i, isolate);
518 Handle<Object> fun = FixedArray::get(*raw_stack_elements, i + 1, isolate);
519 Handle<AbstractCode> code = Handle<AbstractCode>::cast(
520 FixedArray::get(*raw_stack_elements, i + 2, isolate));
521 Handle<Smi> pc =
522 Handle<Smi>::cast(FixedArray::get(*raw_stack_elements, i + 3, isolate));
523
524 Handle<Object> pos =
525 (fun->IsSmi() && pc->value() < 0)
526 ? handle(Smi::FromInt(-1 - pc->value()), isolate)
527 : handle(Smi::FromInt(code->SourcePosition(pc->value())), isolate);
528
529 sloppy_frames--;
530 Handle<Object> strict = isolate->factory()->ToBoolean(sloppy_frames < 0);
531
532 Handle<Object> callsite;
533 ASSIGN_RETURN_ON_EXCEPTION(
534 isolate, callsite,
535 ConstructCallSite(isolate, callsite_ctor, callsite_ctor, recv, fun, pos,
536 strict),
537 FixedArray);
538
539 frames->set(dst_ix++, *callsite);
540 }
541
542 DCHECK_EQ(frame_count, dst_ix);
543 return frames;
544 }
545
546 MaybeHandle<Object> AppendErrorString(Isolate* isolate, Handle<Object> error,
547 IncrementalStringBuilder* builder) {
548 MaybeHandle<String> err_str =
549 ErrorToString(isolate, Handle<Object>::cast(error));
550 if (err_str.is_null()) {
551 // Error.toString threw. Try to return a string representation of the thrown
552 // exception instead.
553
554 DCHECK(isolate->has_pending_exception());
555 Handle<Object> pending_exception =
556 handle(isolate->pending_exception(), isolate);
557 isolate->clear_pending_exception();
558
559 err_str = ErrorToString(isolate, pending_exception);
560 if (err_str.is_null()) {
561 // Formatting the thrown exception threw again, give up.
562 DCHECK(isolate->has_pending_exception());
563 isolate->clear_pending_exception();
564
565 builder->AppendCString("<error>");
566 } else {
567 // Formatted thrown exception successfully, append it.
568 builder->AppendCString("<error: ");
569 builder->AppendString(err_str.ToHandleChecked());
570 builder->AppendCharacter('>');
571 }
572 } else {
573 builder->AppendString(err_str.ToHandleChecked());
574 }
575
576 return error;
577 }
578
579 } // namespace
580
368 MaybeHandle<Object> FormatStackTrace(Isolate* isolate, Handle<JSObject> error, 581 MaybeHandle<Object> FormatStackTrace(Isolate* isolate, Handle<JSObject> error,
369 Handle<Object> stack_trace) { 582 Handle<Object> raw_stack) {
370 // TODO(jgruber): Port FormatStackTrace from JS. 583 Zone zone(isolate->allocator());
371 Handle<JSFunction> fun = isolate->error_format_stack_trace();
372 584
373 int argc = 2; 585 // Create JS CallSite objects from the raw stack frame array.
374 ScopedVector<Handle<Object>> argv(argc);
375 argv[0] = error;
376 argv[1] = stack_trace;
377 586
378 Handle<Object> formatted_stack_trace; 587 Handle<FixedArray> frames;
588 ASSIGN_RETURN_ON_EXCEPTION(isolate, frames,
589 GetStackFrames(isolate, raw_stack), Object);
590
591 // If there's a user-specified "prepareStackFrames" function, call it on the
592 // frames and use its result.
593
594 Handle<JSFunction> global_error = isolate->error_function();
595 Handle<Object> prepare_stack_trace;
379 ASSIGN_RETURN_ON_EXCEPTION( 596 ASSIGN_RETURN_ON_EXCEPTION(
380 isolate, formatted_stack_trace, 597 isolate, prepare_stack_trace,
381 Execution::Call(isolate, fun, error, argc, argv.start()), Object); 598 JSFunction::GetProperty(isolate, global_error, "prepareStackTrace"),
599 Object);
382 600
383 return formatted_stack_trace; 601 // TODO(jgruber): Handle recursive calls.
jgruber 2016/07/29 11:54:37 Is this still needed? And if so, how do we want to
jgruber 2016/07/29 11:56:06 Recursion handling was introduced in a3f16f8e650.
Yang 2016/08/01 06:49:18 I thought we had a test case covering this. Does t
jgruber 2016/08/01 10:52:55 It worked, but more or less accidentally since the
602 if (prepare_stack_trace->IsJSFunction()) {
603 Handle<JSArray> array = isolate->factory()->NewJSArrayWithElements(frames);
604
605 const int argc = 2;
606 ScopedVector<Handle<Object>> argv(argc);
607 argv[0] = error;
608 argv[1] = array;
609
610 Handle<Object> result;
611 ASSIGN_RETURN_ON_EXCEPTION(
612 isolate, result, Execution::Call(isolate, prepare_stack_trace,
613 global_error, argc, argv.start()),
614 Object);
615
616 return result;
617 }
618
619 IncrementalStringBuilder builder(isolate);
620
621 RETURN_ON_EXCEPTION(isolate, AppendErrorString(isolate, error, &builder),
622 Object);
623
624 for (int i = 0; i < frames->length(); i++) {
625 builder.AppendCString("\n at ");
626
627 Handle<Object> frame = FixedArray::get(*frames, i, isolate);
628 MaybeHandle<String> maybe_frame_string = CallSiteToString(isolate, frame);
629 if (maybe_frame_string.is_null()) {
630 // CallSite.toString threw. Try to return a string representation of the
631 // thrown exception instead.
632
633 DCHECK(isolate->has_pending_exception());
634 Handle<Object> pending_exception =
635 handle(isolate->pending_exception(), isolate);
636 isolate->clear_pending_exception();
637
638 maybe_frame_string = ErrorToString(isolate, pending_exception);
639 if (maybe_frame_string.is_null()) {
640 // Formatting the thrown exception threw again, give up.
641
642 builder.AppendCString("<error>");
643 } else {
644 // Formatted thrown exception successfully, append it.
645 builder.AppendCString("<error: ");
646 builder.AppendString(maybe_frame_string.ToHandleChecked());
647 builder.AppendCString("<error>");
648 }
649 } else {
650 // CallSite.toString completed without throwing.
651 builder.AppendString(maybe_frame_string.ToHandleChecked());
652 }
653 }
654
655 RETURN_RESULT(isolate, builder.Finish(), Object);
384 } 656 }
385 657
386 Handle<String> MessageTemplate::FormatMessage(Isolate* isolate, 658 Handle<String> MessageTemplate::FormatMessage(Isolate* isolate,
387 int template_index, 659 int template_index,
388 Handle<Object> arg) { 660 Handle<Object> arg) {
389 Factory* factory = isolate->factory(); 661 Factory* factory = isolate->factory();
390 Handle<String> result_string; 662 Handle<String> result_string;
391 if (arg->IsString()) { 663 if (arg->IsString()) {
392 result_string = Handle<String>::cast(arg); 664 result_string = Handle<String>::cast(arg);
393 } else { 665 } else {
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
514 } 786 }
515 787
516 // Capture a simple stack trace for the stack property. 788 // Capture a simple stack trace for the stack property.
517 RETURN_ON_EXCEPTION(isolate, 789 RETURN_ON_EXCEPTION(isolate,
518 isolate->CaptureAndSetSimpleStackTrace(err, mode, caller), 790 isolate->CaptureAndSetSimpleStackTrace(err, mode, caller),
519 Object); 791 Object);
520 792
521 return err; 793 return err;
522 } 794 }
523 795
796 namespace {
797
798 MaybeHandle<String> GetStringPropertyOrDefault(Isolate* isolate,
799 Handle<JSReceiver> recv,
800 Handle<String> key,
801 Handle<String> default_str) {
802 Handle<Object> obj;
803 ASSIGN_RETURN_ON_EXCEPTION(isolate, obj, JSObject::GetProperty(recv, key),
804 String);
805
806 Handle<String> str;
807 if (obj->IsUndefined(isolate)) {
808 str = default_str;
809 } else {
810 ASSIGN_RETURN_ON_EXCEPTION(isolate, str, Object::ToString(isolate, obj),
811 String);
812 }
813
814 return str;
815 }
816
817 } // namespace
818
819 // ES6 section 19.5.3.4 Error.prototype.toString ( )
820 MaybeHandle<String> ErrorToString(Isolate* isolate, Handle<Object> receiver) {
821 // 1. Let O be the this value.
822 // 2. If Type(O) is not Object, throw a TypeError exception.
823 if (!receiver->IsJSReceiver()) {
824 return isolate->Throw<String>(isolate->factory()->NewTypeError(
825 MessageTemplate::kIncompatibleMethodReceiver,
826 isolate->factory()->NewStringFromAsciiChecked(
827 "Error.prototype.toString"),
828 receiver));
829 }
830 Handle<JSReceiver> recv = Handle<JSReceiver>::cast(receiver);
831
832 // 3. Let name be ? Get(O, "name").
833 // 4. If name is undefined, let name be "Error"; otherwise let name be
834 // ? ToString(name).
835 Handle<String> name_key = isolate->factory()->name_string();
836 Handle<String> name_default = isolate->factory()->Error_string();
837 Handle<String> name;
838 ASSIGN_RETURN_ON_EXCEPTION(
839 isolate, name,
840 GetStringPropertyOrDefault(isolate, recv, name_key, name_default),
841 String);
842
843 // 5. Let msg be ? Get(O, "message").
844 // 6. If msg is undefined, let msg be the empty String; otherwise let msg be
845 // ? ToString(msg).
846 Handle<String> msg_key = isolate->factory()->message_string();
847 Handle<String> msg_default = isolate->factory()->empty_string();
848 Handle<String> msg;
849 ASSIGN_RETURN_ON_EXCEPTION(
850 isolate, msg,
851 GetStringPropertyOrDefault(isolate, recv, msg_key, msg_default), String);
852
853 // 7. If name is the empty String, return msg.
854 // 8. If msg is the empty String, return name.
855 if (name->length() == 0) return msg;
856 if (msg->length() == 0) return name;
857
858 // 9. Return the result of concatenating name, the code unit 0x003A (COLON),
859 // the code unit 0x0020 (SPACE), and msg.
860 IncrementalStringBuilder builder(isolate);
861 builder.AppendString(name);
862 builder.AppendCString(": ");
863 builder.AppendString(msg);
864
865 Handle<String> result;
866 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, builder.Finish(), String);
867 return result;
868 }
869
870 #define SET_CALLSITE_PROPERTY(target, key, value) \
871 RETURN_ON_EXCEPTION( \
872 isolate, JSObject::SetOwnPropertyIgnoreAttributes( \
873 target, isolate->factory()->key(), value, DONT_ENUM), \
874 Object)
875
876 MaybeHandle<Object> ConstructCallSite(Isolate* isolate,
877 Handle<JSFunction> target,
878 Handle<Object> new_target,
879 Handle<Object> receiver,
880 Handle<Object> fun, Handle<Object> pos,
881 Handle<Object> strict_mode) {
882 // Create the JS object.
883
884 Handle<JSReceiver> new_target_recv =
885 new_target->IsJSReceiver() ? Handle<JSReceiver>::cast(new_target)
886 : Handle<JSReceiver>::cast(target);
887
888 Handle<JSObject> obj;
889 ASSIGN_RETURN_ON_EXCEPTION(isolate, obj,
890 JSObject::New(target, new_target_recv), Object);
891
892 // For wasm frames, receiver is the wasm object and fun is the function index
893 // instead of an actual function.
894 const bool is_wasm_object =
895 receiver->IsJSObject() && wasm::IsWasmObject(JSObject::cast(*receiver));
896 if (!fun->IsJSFunction() && !is_wasm_object) {
897 THROW_NEW_ERROR(isolate,
898 NewTypeError(MessageTemplate::kCallSiteExpectsFunction,
899 Object::TypeOf(isolate, receiver),
900 Object::TypeOf(isolate, fun)),
901 Object);
902 }
903
904 if (is_wasm_object) {
905 DCHECK(!fun->IsJSFunction());
906 SET_CALLSITE_PROPERTY(obj, call_site_wasm_obj_symbol, receiver);
907
908 Handle<Object> fun_index;
909 ASSIGN_RETURN_ON_EXCEPTION(isolate, fun_index,
910 Object::ToUint32(isolate, fun), Object);
911 SET_CALLSITE_PROPERTY(obj, call_site_wasm_func_index_symbol, fun);
912 } else {
913 DCHECK(fun->IsJSFunction());
914 SET_CALLSITE_PROPERTY(obj, call_site_receiver_symbol, receiver);
915 SET_CALLSITE_PROPERTY(obj, call_site_function_symbol, fun);
916 }
917
918 Handle<Object> pos_int32;
919 ASSIGN_RETURN_ON_EXCEPTION(isolate, pos_int32, Object::ToInt32(isolate, pos),
920 Object);
921 SET_CALLSITE_PROPERTY(obj, call_site_position_symbol, pos_int32);
922 SET_CALLSITE_PROPERTY(
923 obj, call_site_strict_symbol,
924 isolate->factory()->ToBoolean(strict_mode->BooleanValue()));
925
926 return obj;
927 }
928
929 #undef SET_CALLSITE_PROPERTY
930
931 namespace {
932
933 bool IsNonEmptyString(Handle<Object> object) {
934 return (object->IsString() && String::cast(*object)->length() > 0);
935 }
936
937 MaybeHandle<JSObject> AppendWasmToString(Isolate* isolate,
938 Handle<JSObject> recv,
939 CallSite* call_site,
940 IncrementalStringBuilder* builder) {
941 Handle<Object> name = call_site->GetFunctionName();
942 if (name->IsNull(isolate)) {
943 builder->AppendCString("<WASM UNNAMED>");
944 } else {
945 DCHECK(name->IsString());
946 builder->AppendString(Handle<String>::cast(name));
947 }
948
949 builder->AppendCString(" (<WASM>[");
950
951 Handle<String> ix = isolate->factory()->NumberToString(
952 handle(Smi::FromInt(call_site->wasm_func_index()), isolate));
953 builder->AppendString(ix);
954
955 builder->AppendCString("]+");
956
957 Handle<Object> pos;
958 ASSIGN_RETURN_ON_EXCEPTION(
959 isolate, pos, JSObject::GetProperty(
960 recv, isolate->factory()->call_site_position_symbol()),
961 JSObject);
962 DCHECK(pos->IsNumber());
963 builder->AppendString(isolate->factory()->NumberToString(pos));
964 builder->AppendCString(")");
965
966 return recv;
967 }
968
969 MaybeHandle<JSObject> AppendFileLocation(Isolate* isolate,
970 Handle<JSObject> recv,
971 CallSite* call_site,
972 IncrementalStringBuilder* builder) {
973 if (call_site->IsNative()) {
974 builder->AppendCString("native");
975 return recv;
976 }
977
978 Handle<Object> file_name = call_site->GetScriptNameOrSourceUrl();
979 if (!file_name->IsString() && call_site->IsEval()) {
980 Handle<Object> eval_origin = call_site->GetEvalOrigin();
981 DCHECK(eval_origin->IsString());
982 builder->AppendString(Handle<String>::cast(eval_origin));
983 builder->AppendCString(", "); // Expecting source position to follow.
984 }
985
986 if (IsNonEmptyString(file_name)) {
987 builder->AppendString(Handle<String>::cast(file_name));
988 } else {
989 // Source code does not originate from a file and is not native, but we
990 // can still get the source position inside the source string, e.g. in
991 // an eval string.
992 builder->AppendCString("<anonymous>");
993 }
994
995 int line_number = call_site->GetLineNumber();
996 if (line_number != -1) {
997 builder->AppendCharacter(':');
998 Handle<String> line_string = isolate->factory()->NumberToString(
999 handle(Smi::FromInt(line_number), isolate), isolate);
1000 builder->AppendString(line_string);
1001
1002 int column_number = call_site->GetColumnNumber();
1003 if (column_number != -1) {
1004 builder->AppendCharacter(':');
1005 Handle<String> column_string = isolate->factory()->NumberToString(
1006 handle(Smi::FromInt(column_number), isolate), isolate);
1007 builder->AppendString(column_string);
1008 }
1009 }
1010
1011 return recv;
1012 }
1013
1014 int StringIndexOf(Isolate* isolate, Handle<String> subject,
1015 Handle<String> pattern) {
1016 if (pattern->length() > subject->length()) return -1;
1017 return String::IndexOf(isolate, subject, pattern, 0);
1018 }
1019
1020 // Returns true iff
1021 // 1. the subject ends with '.' + pattern, or
1022 // 2. subject == pattern.
1023 bool StringEndsWithMethodName(Isolate* isolate, Handle<String> subject,
1024 Handle<String> pattern) {
1025 if (String::Equals(subject, pattern)) return true;
1026
1027 FlatStringReader subject_reader(isolate, String::Flatten(subject));
1028 FlatStringReader pattern_reader(isolate, String::Flatten(pattern));
1029
1030 int pattern_index = pattern_reader.length() - 1;
1031 int subject_index = subject_reader.length() - 1;
1032 for (int i = 0; i <= pattern_reader.length(); i++) { // Iterate over len + 1.
1033 if (subject_index < 0) {
1034 return false;
1035 }
1036
1037 const uc32 subject_char = subject_reader.Get(subject_index);
1038 if (i == pattern_reader.length()) {
1039 if (subject_char != '.') return false;
1040 } else if (subject_char != pattern_reader.Get(pattern_index)) {
1041 return false;
1042 }
1043
1044 pattern_index--;
1045 subject_index--;
1046 }
1047
1048 return true;
1049 }
1050
1051 MaybeHandle<JSObject> AppendMethodCall(Isolate* isolate, Handle<JSObject> recv,
1052 CallSite* call_site,
1053 IncrementalStringBuilder* builder) {
1054 Handle<Object> type_name = call_site->GetTypeName();
1055 Handle<Object> method_name = call_site->GetMethodName();
1056 Handle<Object> function_name = call_site->GetFunctionName();
1057
1058 if (IsNonEmptyString(function_name)) {
1059 Handle<String> function_string = Handle<String>::cast(function_name);
1060 if (IsNonEmptyString(type_name)) {
1061 Handle<String> type_string = Handle<String>::cast(type_name);
1062 bool starts_with_type_name =
1063 (StringIndexOf(isolate, function_string, type_string) == 0);
1064 if (!starts_with_type_name) {
1065 builder->AppendString(type_string);
1066 builder->AppendCharacter('.');
1067 }
1068 }
1069 builder->AppendString(function_string);
1070
1071 if (IsNonEmptyString(method_name)) {
1072 Handle<String> method_string = Handle<String>::cast(method_name);
1073 if (!StringEndsWithMethodName(isolate, function_string, method_string)) {
1074 builder->AppendCString(" [as ");
1075 builder->AppendString(method_string);
1076 builder->AppendCharacter(']');
1077 }
1078 }
1079 } else {
1080 builder->AppendString(Handle<String>::cast(type_name));
1081 builder->AppendCharacter('.');
1082 if (IsNonEmptyString(method_name)) {
1083 builder->AppendString(Handle<String>::cast(method_name));
1084 } else {
1085 builder->AppendCString("<anonymous>");
1086 }
1087 }
1088
1089 return recv;
1090 }
1091
1092 } // namespace
1093
1094 MaybeHandle<String> CallSiteToString(Isolate* isolate,
1095 Handle<Object> receiver) {
1096 if (!receiver->IsJSObject()) {
1097 THROW_NEW_ERROR(
1098 isolate,
1099 NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
1100 isolate->factory()->NewStringFromAsciiChecked("toString"),
1101 receiver),
1102 String);
1103 }
1104 Handle<JSObject> recv = Handle<JSObject>::cast(receiver);
1105
1106 if (!JSReceiver::HasOwnProperty(
1107 recv, isolate->factory()->call_site_position_symbol())
1108 .FromMaybe(false)) {
1109 THROW_NEW_ERROR(
1110 isolate,
1111 NewTypeError(MessageTemplate::kCallSiteMethod,
1112 isolate->factory()->NewStringFromAsciiChecked("toString")),
1113 String);
1114 }
1115
1116 IncrementalStringBuilder builder(isolate);
1117
1118 CallSite call_site(isolate, recv);
1119 if (call_site.IsWasm()) {
1120 RETURN_ON_EXCEPTION(isolate,
1121 AppendWasmToString(isolate, recv, &call_site, &builder),
1122 String);
1123 RETURN_RESULT(isolate, builder.Finish(), String);
1124 }
1125
1126 DCHECK(!call_site.IsWasm());
1127 Handle<Object> function_name = call_site.GetFunctionName();
1128
1129 const bool is_toplevel = call_site.IsToplevel();
1130 const bool is_constructor = call_site.IsConstructor();
1131 const bool is_method_call = !(is_toplevel || is_constructor);
1132
1133 if (is_method_call) {
1134 RETURN_ON_EXCEPTION(
1135 isolate, AppendMethodCall(isolate, recv, &call_site, &builder), String);
1136 } else if (is_constructor) {
1137 builder.AppendCString("new ");
1138 if (IsNonEmptyString(function_name)) {
1139 builder.AppendString(Handle<String>::cast(function_name));
1140 } else {
1141 builder.AppendCString("<anonymous>");
1142 }
1143 } else if (IsNonEmptyString(function_name)) {
1144 builder.AppendString(Handle<String>::cast(function_name));
1145 } else {
1146 RETURN_ON_EXCEPTION(isolate,
1147 AppendFileLocation(isolate, recv, &call_site, &builder),
1148 String);
1149 RETURN_RESULT(isolate, builder.Finish(), String);
1150 }
1151
1152 builder.AppendCString(" (");
1153 RETURN_ON_EXCEPTION(
1154 isolate, AppendFileLocation(isolate, recv, &call_site, &builder), String);
1155 builder.AppendCString(")");
1156
1157 RETURN_RESULT(isolate, builder.Finish(), String);
1158 }
1159
524 } // namespace internal 1160 } // namespace internal
525 } // namespace v8 1161 } // namespace v8
OLDNEW
« src/messages.h ('K') | « src/messages.h ('k') | src/runtime/runtime.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698