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

Side by Side Diff: src/messages.cc

Issue 2275233002: Refactor call site handling for stack formatting (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Address comments Created 4 years, 3 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
« no previous file with comments | « src/messages.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/execution.h" 10 #include "src/execution.h"
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 Handle<Object> arg = Handle<Object>(message->argument(), isolate); 157 Handle<Object> arg = Handle<Object>(message->argument(), isolate);
158 return MessageTemplate::FormatMessage(isolate, message->type(), arg); 158 return MessageTemplate::FormatMessage(isolate, message->type(), arg);
159 } 159 }
160 160
161 std::unique_ptr<char[]> MessageHandler::GetLocalizedMessage( 161 std::unique_ptr<char[]> MessageHandler::GetLocalizedMessage(
162 Isolate* isolate, Handle<Object> data) { 162 Isolate* isolate, Handle<Object> data) {
163 HandleScope scope(isolate); 163 HandleScope scope(isolate);
164 return GetMessage(isolate, data)->ToCString(DISALLOW_NULLS); 164 return GetMessage(isolate, data)->ToCString(DISALLOW_NULLS);
165 } 165 }
166 166
167 void JSStackFrame::FromFrameArray(Isolate* isolate, Handle<FrameArray> array,
168 int frame_ix) {
169 DCHECK(!array->IsWasmFrame(frame_ix));
170 isolate_ = isolate;
171 receiver_ = handle(array->Receiver(frame_ix), isolate);
172 function_ = handle(array->Function(frame_ix), isolate);
173 code_ = handle(array->Code(frame_ix), isolate);
174 offset_ = array->Offset(frame_ix)->value();
167 175
168 CallSite::CallSite(Isolate* isolate, Handle<JSObject> call_site_obj) 176 const int flags = array->Flags(frame_ix)->value();
169 : isolate_(isolate) { 177 force_constructor_ = (flags & FrameArray::kForceConstructor) != 0;
170 Handle<Object> maybe_function = JSObject::GetDataProperty( 178 is_strict_ = (flags & FrameArray::kIsStrict) != 0;
171 call_site_obj, isolate->factory()->call_site_function_symbol());
172 if (maybe_function->IsJSFunction()) {
173 // javascript
174 fun_ = Handle<JSFunction>::cast(maybe_function);
175 receiver_ = JSObject::GetDataProperty(
176 call_site_obj, isolate->factory()->call_site_receiver_symbol());
177 } else {
178 Handle<Object> maybe_wasm_func_index = JSObject::GetDataProperty(
179 call_site_obj, isolate->factory()->call_site_wasm_func_index_symbol());
180 if (!maybe_wasm_func_index->IsSmi()) {
181 // invalid: neither javascript nor wasm
182 return;
183 }
184 // wasm
185 wasm_obj_ = Handle<JSObject>::cast(JSObject::GetDataProperty(
186 call_site_obj, isolate->factory()->call_site_wasm_obj_symbol()));
187 wasm_func_index_ = Smi::cast(*maybe_wasm_func_index)->value();
188 DCHECK(static_cast<int>(wasm_func_index_) >= 0);
189 }
190
191 CHECK(JSObject::GetDataProperty(
192 call_site_obj, isolate->factory()->call_site_position_symbol())
193 ->ToInt32(&pos_));
194 } 179 }
195 180
181 JSStackFrame::JSStackFrame(Isolate* isolate, Handle<Object> receiver,
182 Handle<JSFunction> function,
183 Handle<AbstractCode> code, int offset)
184 : isolate_(isolate),
185 receiver_(receiver),
186 function_(function),
187 code_(code),
188 offset_(offset),
189 force_constructor_(false),
190 is_strict_(false) {}
196 191
197 Handle<Object> CallSite::GetFileName() { 192 JSStackFrame::JSStackFrame() {}
198 if (!IsJavaScript()) return isolate_->factory()->null_value(); 193
199 Object* script = fun_->shared()->script(); 194 Handle<Object> JSStackFrame::GetFunction() const {
200 if (!script->IsScript()) return isolate_->factory()->null_value(); 195 return Handle<Object>::cast(function_);
201 return Handle<Object>(Script::cast(script)->name(), isolate_);
202 } 196 }
203 197
198 Handle<Object> JSStackFrame::GetFileName() {
199 if (!HasScript()) return isolate_->factory()->null_value();
200 return handle(GetScript()->name(), isolate_);
201 }
204 202
205 Handle<Object> CallSite::GetFunctionName() { 203 Handle<Object> JSStackFrame::GetFunctionName() {
206 if (IsWasm()) { 204 Handle<String> result = JSFunction::GetName(function_);
207 return wasm::GetWasmFunctionNameOrNull(isolate_, wasm_obj_,
208 wasm_func_index_);
209 }
210 Handle<String> result = JSFunction::GetName(fun_);
211 if (result->length() != 0) return result; 205 if (result->length() != 0) return result;
212 206
213 Handle<Object> script(fun_->shared()->script(), isolate_); 207 if (HasScript() &&
214 if (script->IsScript() && 208 GetScript()->compilation_type() == Script::COMPILATION_TYPE_EVAL) {
215 Handle<Script>::cast(script)->compilation_type() ==
216 Script::COMPILATION_TYPE_EVAL) {
217 return isolate_->factory()->eval_string(); 209 return isolate_->factory()->eval_string();
218 } 210 }
219 return isolate_->factory()->null_value(); 211 return isolate_->factory()->null_value();
220 } 212 }
221 213
222 Handle<Object> CallSite::GetScriptNameOrSourceUrl() { 214 Handle<Object> JSStackFrame::GetScriptNameOrSourceUrl() {
223 if (!IsJavaScript()) return isolate_->factory()->null_value(); 215 if (!HasScript()) return isolate_->factory()->null_value();
224 Object* script_obj = fun_->shared()->script(); 216 Handle<Script> script = GetScript();
225 if (!script_obj->IsScript()) return isolate_->factory()->null_value();
226 Handle<Script> script(Script::cast(script_obj), isolate_);
227 Object* source_url = script->source_url(); 217 Object* source_url = script->source_url();
228 if (source_url->IsString()) return Handle<Object>(source_url, isolate_); 218 return (source_url->IsString()) ? handle(source_url, isolate_)
229 return Handle<Object>(script->name(), isolate_); 219 : handle(script->name(), isolate_);
230 } 220 }
231 221
222 namespace {
223
232 bool CheckMethodName(Isolate* isolate, Handle<JSObject> obj, Handle<Name> name, 224 bool CheckMethodName(Isolate* isolate, Handle<JSObject> obj, Handle<Name> name,
233 Handle<JSFunction> fun, 225 Handle<JSFunction> fun,
234 LookupIterator::Configuration config) { 226 LookupIterator::Configuration config) {
235 LookupIterator iter = 227 LookupIterator iter =
236 LookupIterator::PropertyOrElement(isolate, obj, name, config); 228 LookupIterator::PropertyOrElement(isolate, obj, name, config);
237 if (iter.state() == LookupIterator::DATA) { 229 if (iter.state() == LookupIterator::DATA) {
238 return iter.GetDataValue().is_identical_to(fun); 230 return iter.GetDataValue().is_identical_to(fun);
239 } else if (iter.state() == LookupIterator::ACCESSOR) { 231 } else if (iter.state() == LookupIterator::ACCESSOR) {
240 Handle<Object> accessors = iter.GetAccessors(); 232 Handle<Object> accessors = iter.GetAccessors();
241 if (accessors->IsAccessorPair()) { 233 if (accessors->IsAccessorPair()) {
242 Handle<AccessorPair> pair = Handle<AccessorPair>::cast(accessors); 234 Handle<AccessorPair> pair = Handle<AccessorPair>::cast(accessors);
243 return pair->getter() == *fun || pair->setter() == *fun; 235 return pair->getter() == *fun || pair->setter() == *fun;
244 } 236 }
245 } 237 }
246 return false; 238 return false;
247 } 239 }
248 240
241 } // namespace
249 242
250 Handle<Object> CallSite::GetMethodName() { 243 Handle<Object> JSStackFrame::GetMethodName() {
251 if (!IsJavaScript() || receiver_->IsNull(isolate_) || 244 if (receiver_->IsNull(isolate_) || receiver_->IsUndefined(isolate_)) {
252 receiver_->IsUndefined(isolate_)) {
253 return isolate_->factory()->null_value(); 245 return isolate_->factory()->null_value();
254 } 246 }
247
255 Handle<JSReceiver> receiver = 248 Handle<JSReceiver> receiver =
256 Object::ToObject(isolate_, receiver_).ToHandleChecked(); 249 Object::ToObject(isolate_, receiver_).ToHandleChecked();
257 if (!receiver->IsJSObject()) { 250 if (!receiver->IsJSObject()) {
258 return isolate_->factory()->null_value(); 251 return isolate_->factory()->null_value();
259 } 252 }
260 253
261 Handle<JSObject> obj = Handle<JSObject>::cast(receiver); 254 Handle<JSObject> obj = Handle<JSObject>::cast(receiver);
262 Handle<Object> function_name(fun_->shared()->name(), isolate_); 255 Handle<Object> function_name(function_->shared()->name(), isolate_);
263 if (function_name->IsString()) { 256 if (function_name->IsString()) {
264 Handle<String> name = Handle<String>::cast(function_name); 257 Handle<String> name = Handle<String>::cast(function_name);
265 // ES2015 gives getters and setters name prefixes which must 258 // ES2015 gives getters and setters name prefixes which must
266 // be stripped to find the property name. 259 // be stripped to find the property name.
267 if (name->IsUtf8EqualTo(CStrVector("get "), true) || 260 if (name->IsUtf8EqualTo(CStrVector("get "), true) ||
268 name->IsUtf8EqualTo(CStrVector("set "), true)) { 261 name->IsUtf8EqualTo(CStrVector("set "), true)) {
269 name = isolate_->factory()->NewProperSubString(name, 4, name->length()); 262 name = isolate_->factory()->NewProperSubString(name, 4, name->length());
270 } 263 }
271 if (CheckMethodName(isolate_, obj, name, fun_, 264 if (CheckMethodName(isolate_, obj, name, function_,
272 LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR)) { 265 LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR)) {
273 return name; 266 return name;
274 } 267 }
275 } 268 }
276 269
277 HandleScope outer_scope(isolate_); 270 HandleScope outer_scope(isolate_);
278 Handle<Object> result; 271 Handle<Object> result;
279 for (PrototypeIterator iter(isolate_, obj, kStartAtReceiver); !iter.IsAtEnd(); 272 for (PrototypeIterator iter(isolate_, obj, kStartAtReceiver); !iter.IsAtEnd();
280 iter.Advance()) { 273 iter.Advance()) {
281 Handle<Object> current = PrototypeIterator::GetCurrent(iter); 274 Handle<Object> current = PrototypeIterator::GetCurrent(iter);
282 if (!current->IsJSObject()) break; 275 if (!current->IsJSObject()) break;
283 Handle<JSObject> current_obj = Handle<JSObject>::cast(current); 276 Handle<JSObject> current_obj = Handle<JSObject>::cast(current);
284 if (current_obj->IsAccessCheckNeeded()) break; 277 if (current_obj->IsAccessCheckNeeded()) break;
285 Handle<FixedArray> keys = 278 Handle<FixedArray> keys =
286 KeyAccumulator::GetOwnEnumPropertyKeys(isolate_, current_obj); 279 KeyAccumulator::GetOwnEnumPropertyKeys(isolate_, current_obj);
287 for (int i = 0; i < keys->length(); i++) { 280 for (int i = 0; i < keys->length(); i++) {
288 HandleScope inner_scope(isolate_); 281 HandleScope inner_scope(isolate_);
289 if (!keys->get(i)->IsName()) continue; 282 if (!keys->get(i)->IsName()) continue;
290 Handle<Name> name_key(Name::cast(keys->get(i)), isolate_); 283 Handle<Name> name_key(Name::cast(keys->get(i)), isolate_);
291 if (!CheckMethodName(isolate_, current_obj, name_key, fun_, 284 if (!CheckMethodName(isolate_, current_obj, name_key, function_,
292 LookupIterator::OWN_SKIP_INTERCEPTOR)) 285 LookupIterator::OWN_SKIP_INTERCEPTOR))
293 continue; 286 continue;
294 // Return null in case of duplicates to avoid confusion. 287 // Return null in case of duplicates to avoid confusion.
295 if (!result.is_null()) return isolate_->factory()->null_value(); 288 if (!result.is_null()) return isolate_->factory()->null_value();
296 result = inner_scope.CloseAndEscape(name_key); 289 result = inner_scope.CloseAndEscape(name_key);
297 } 290 }
298 } 291 }
299 292
300 if (!result.is_null()) return outer_scope.CloseAndEscape(result); 293 if (!result.is_null()) return outer_scope.CloseAndEscape(result);
301 return isolate_->factory()->null_value(); 294 return isolate_->factory()->null_value();
302 } 295 }
303 296
304 Handle<Object> CallSite::GetTypeName() {
305 // TODO(jgruber): Check for strict/constructor here as in
306 // CallSitePrototypeGetThis.
307
308 if (receiver_->IsNull(isolate_) || receiver_->IsUndefined(isolate_))
309 return isolate_->factory()->null_value();
310
311 if (receiver_->IsJSProxy()) return isolate_->factory()->Proxy_string();
312
313 Handle<JSReceiver> receiver_object =
314 Object::ToObject(isolate_, receiver_).ToHandleChecked();
315 return JSReceiver::GetConstructorName(receiver_object);
316 }
317
318 namespace { 297 namespace {
319 298
320 Object* EvalFromFunctionName(Isolate* isolate, Handle<Script> script) { 299 Object* EvalFromFunctionName(Isolate* isolate, Handle<Script> script) {
321 if (script->eval_from_shared()->IsUndefined(isolate)) 300 if (script->eval_from_shared()->IsUndefined(isolate))
322 return *isolate->factory()->undefined_value(); 301 return *isolate->factory()->undefined_value();
323 302
324 Handle<SharedFunctionInfo> shared( 303 Handle<SharedFunctionInfo> shared(
325 SharedFunctionInfo::cast(script->eval_from_shared())); 304 SharedFunctionInfo::cast(script->eval_from_shared()));
326 // Find the name of the function calling eval. 305 // Find the name of the function calling eval.
327 if (shared->name()->BooleanValue()) { 306 if (shared->name()->BooleanValue()) {
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
407 builder.AppendCString(")"); 386 builder.AppendCString(")");
408 } 387 }
409 388
410 Handle<String> result; 389 Handle<String> result;
411 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, builder.Finish(), String); 390 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, builder.Finish(), String);
412 return result; 391 return result;
413 } 392 }
414 393
415 } // namespace 394 } // namespace
416 395
417 Handle<Object> CallSite::GetEvalOrigin() { 396 Handle<Object> JSStackFrame::GetTypeName() {
418 if (IsWasm()) return isolate_->factory()->undefined_value(); 397 // TODO(jgruber): Check for strict/constructor here as in
419 DCHECK(IsJavaScript()); 398 // CallSitePrototypeGetThis.
420 399
421 Handle<Object> script = handle(fun_->shared()->script(), isolate_); 400 if (receiver_->IsNull(isolate_) || receiver_->IsUndefined(isolate_))
422 if (!script->IsScript()) return isolate_->factory()->undefined_value(); 401 return isolate_->factory()->null_value();
423 402
424 return FormatEvalOrigin(isolate_, Handle<Script>::cast(script)) 403 if (receiver_->IsJSProxy()) return isolate_->factory()->Proxy_string();
425 .ToHandleChecked(); 404
426 } 405 Handle<JSReceiver> receiver_object =
427 406 Object::ToObject(isolate_, receiver_).ToHandleChecked();
428 int CallSite::GetLineNumber() { 407 return JSReceiver::GetConstructorName(receiver_object);
429 if (pos_ >= 0 && IsJavaScript()) { 408 }
430 Handle<Object> script_obj(fun_->shared()->script(), isolate_); 409
431 if (script_obj->IsScript()) { 410 Handle<Object> JSStackFrame::GetEvalOrigin() {
432 Handle<Script> script = Handle<Script>::cast(script_obj); 411 if (!HasScript()) return isolate_->factory()->undefined_value();
433 return Script::GetLineNumber(script, pos_) + 1; 412 return FormatEvalOrigin(isolate_, GetScript()).ToHandleChecked();
434 } 413 }
435 } 414
415 int JSStackFrame::GetLineNumber() {
416 DCHECK_LE(0, GetPosition());
417 if (HasScript()) return Script::GetLineNumber(GetScript(), GetPosition()) + 1;
436 return -1; 418 return -1;
437 } 419 }
438 420
439 421 int JSStackFrame::GetColumnNumber() {
440 int CallSite::GetColumnNumber() { 422 DCHECK_LE(0, GetPosition());
441 if (pos_ >= 0 && IsJavaScript()) { 423 if (HasScript()) {
442 Handle<Object> script_obj(fun_->shared()->script(), isolate_); 424 return Script::GetColumnNumber(GetScript(), GetPosition()) + 1;
443 if (script_obj->IsScript()) {
444 Handle<Script> script = Handle<Script>::cast(script_obj);
445 return Script::GetColumnNumber(script, pos_) + 1;
446 }
447 } 425 }
448 return -1; 426 return -1;
449 } 427 }
450 428
451 429 bool JSStackFrame::IsNative() {
452 bool CallSite::IsNative() { 430 return HasScript() && GetScript()->type() == Script::TYPE_NATIVE;
453 if (!IsJavaScript()) return false; 431 }
454 Handle<Object> script(fun_->shared()->script(), isolate_); 432
455 return script->IsScript() && 433 bool JSStackFrame::IsToplevel() {
456 Handle<Script>::cast(script)->type() == Script::TYPE_NATIVE;
457 }
458
459
460 bool CallSite::IsToplevel() {
461 if (IsWasm()) return false;
462 return receiver_->IsJSGlobalProxy() || receiver_->IsNull(isolate_) || 434 return receiver_->IsJSGlobalProxy() || receiver_->IsNull(isolate_) ||
463 receiver_->IsUndefined(isolate_); 435 receiver_->IsUndefined(isolate_);
464 } 436 }
465 437
466 438 bool JSStackFrame::IsEval() {
467 bool CallSite::IsEval() { 439 return HasScript() &&
468 if (!IsJavaScript()) return false; 440 GetScript()->compilation_type() == Script::COMPILATION_TYPE_EVAL;
469 Handle<Object> script(fun_->shared()->script(), isolate_); 441 }
470 return script->IsScript() && 442
471 Handle<Script>::cast(script)->compilation_type() == 443 bool JSStackFrame::IsConstructor() {
472 Script::COMPILATION_TYPE_EVAL; 444 if (force_constructor_) return true;
473 } 445 if (!receiver_->IsJSObject()) return false;
474
475
476 bool CallSite::IsConstructor() {
477 // Builtin exit frames mark constructors by passing a special symbol as the
478 // receiver.
479 Object* ctor_symbol = isolate_->heap()->call_site_constructor_symbol();
480 if (*receiver_ == ctor_symbol) return true;
481 if (!IsJavaScript() || !receiver_->IsJSObject()) return false;
482 Handle<Object> constructor = 446 Handle<Object> constructor =
483 JSReceiver::GetDataProperty(Handle<JSObject>::cast(receiver_), 447 JSReceiver::GetDataProperty(Handle<JSObject>::cast(receiver_),
484 isolate_->factory()->constructor_string()); 448 isolate_->factory()->constructor_string());
485 return constructor.is_identical_to(fun_); 449 return constructor.is_identical_to(function_);
486 } 450 }
487 451
488 namespace { 452 namespace {
489 453
454 bool IsNonEmptyString(Handle<Object> object) {
455 return (object->IsString() && String::cast(*object)->length() > 0);
456 }
457
458 void AppendFileLocation(Isolate* isolate, JSStackFrame* call_site,
459 IncrementalStringBuilder* builder) {
460 if (call_site->IsNative()) {
461 builder->AppendCString("native");
462 return;
463 }
464
465 Handle<Object> file_name = call_site->GetScriptNameOrSourceUrl();
466 if (!file_name->IsString() && call_site->IsEval()) {
467 Handle<Object> eval_origin = call_site->GetEvalOrigin();
468 DCHECK(eval_origin->IsString());
469 builder->AppendString(Handle<String>::cast(eval_origin));
470 builder->AppendCString(", "); // Expecting source position to follow.
471 }
472
473 if (IsNonEmptyString(file_name)) {
474 builder->AppendString(Handle<String>::cast(file_name));
475 } else {
476 // Source code does not originate from a file and is not native, but we
477 // can still get the source position inside the source string, e.g. in
478 // an eval string.
479 builder->AppendCString("<anonymous>");
480 }
481
482 int line_number = call_site->GetLineNumber();
483 if (line_number != -1) {
484 builder->AppendCharacter(':');
485 Handle<String> line_string = isolate->factory()->NumberToString(
486 handle(Smi::FromInt(line_number), isolate), isolate);
487 builder->AppendString(line_string);
488
489 int column_number = call_site->GetColumnNumber();
490 if (column_number != -1) {
491 builder->AppendCharacter(':');
492 Handle<String> column_string = isolate->factory()->NumberToString(
493 handle(Smi::FromInt(column_number), isolate), isolate);
494 builder->AppendString(column_string);
495 }
496 }
497 }
498
499 int StringIndexOf(Isolate* isolate, Handle<String> subject,
500 Handle<String> pattern) {
501 if (pattern->length() > subject->length()) return -1;
502 return String::IndexOf(isolate, subject, pattern, 0);
503 }
504
505 // Returns true iff
506 // 1. the subject ends with '.' + pattern, or
507 // 2. subject == pattern.
508 bool StringEndsWithMethodName(Isolate* isolate, Handle<String> subject,
509 Handle<String> pattern) {
510 if (String::Equals(subject, pattern)) return true;
511
512 FlatStringReader subject_reader(isolate, String::Flatten(subject));
513 FlatStringReader pattern_reader(isolate, String::Flatten(pattern));
514
515 int pattern_index = pattern_reader.length() - 1;
516 int subject_index = subject_reader.length() - 1;
517 for (int i = 0; i <= pattern_reader.length(); i++) { // Iterate over len + 1.
518 if (subject_index < 0) {
519 return false;
520 }
521
522 const uc32 subject_char = subject_reader.Get(subject_index);
523 if (i == pattern_reader.length()) {
524 if (subject_char != '.') return false;
525 } else if (subject_char != pattern_reader.Get(pattern_index)) {
526 return false;
527 }
528
529 pattern_index--;
530 subject_index--;
531 }
532
533 return true;
534 }
535
536 void AppendMethodCall(Isolate* isolate, JSStackFrame* call_site,
537 IncrementalStringBuilder* builder) {
538 Handle<Object> type_name = call_site->GetTypeName();
539 Handle<Object> method_name = call_site->GetMethodName();
540 Handle<Object> function_name = call_site->GetFunctionName();
541
542 if (IsNonEmptyString(function_name)) {
543 Handle<String> function_string = Handle<String>::cast(function_name);
544 if (IsNonEmptyString(type_name)) {
545 Handle<String> type_string = Handle<String>::cast(type_name);
546 bool starts_with_type_name =
547 (StringIndexOf(isolate, function_string, type_string) == 0);
548 if (!starts_with_type_name) {
549 builder->AppendString(type_string);
550 builder->AppendCharacter('.');
551 }
552 }
553 builder->AppendString(function_string);
554
555 if (IsNonEmptyString(method_name)) {
556 Handle<String> method_string = Handle<String>::cast(method_name);
557 if (!StringEndsWithMethodName(isolate, function_string, method_string)) {
558 builder->AppendCString(" [as ");
559 builder->AppendString(method_string);
560 builder->AppendCharacter(']');
561 }
562 }
563 } else {
564 builder->AppendString(Handle<String>::cast(type_name));
565 builder->AppendCharacter('.');
566 if (IsNonEmptyString(method_name)) {
567 builder->AppendString(Handle<String>::cast(method_name));
568 } else {
569 builder->AppendCString("<anonymous>");
570 }
571 }
572 }
573
574 } // namespace
575
576 MaybeHandle<String> JSStackFrame::ToString() {
577 IncrementalStringBuilder builder(isolate_);
578
579 Handle<Object> function_name = GetFunctionName();
580
581 const bool is_toplevel = IsToplevel();
582 const bool is_constructor = IsConstructor();
583 const bool is_method_call = !(is_toplevel || is_constructor);
584
585 if (is_method_call) {
586 AppendMethodCall(isolate_, this, &builder);
587 } else if (is_constructor) {
588 builder.AppendCString("new ");
589 if (IsNonEmptyString(function_name)) {
590 builder.AppendString(Handle<String>::cast(function_name));
591 } else {
592 builder.AppendCString("<anonymous>");
593 }
594 } else if (IsNonEmptyString(function_name)) {
595 builder.AppendString(Handle<String>::cast(function_name));
596 } else {
597 AppendFileLocation(isolate_, this, &builder);
598 RETURN_RESULT(isolate_, builder.Finish(), String);
599 }
600
601 builder.AppendCString(" (");
602 AppendFileLocation(isolate_, this, &builder);
603 builder.AppendCString(")");
604
605 RETURN_RESULT(isolate_, builder.Finish(), String);
606 }
607
608 int JSStackFrame::GetPosition() const { return code_->SourcePosition(offset_); }
609
610 bool JSStackFrame::HasScript() const {
611 return function_->shared()->script()->IsScript();
612 }
613
614 Handle<Script> JSStackFrame::GetScript() const {
615 return handle(Script::cast(function_->shared()->script()), isolate_);
616 }
617
618 void WasmStackFrame::FromFrameArray(Isolate* isolate, Handle<FrameArray> array,
619 int frame_ix) {
620 DCHECK(array->IsWasmFrame(frame_ix));
621 isolate_ = isolate;
622 wasm_obj_ = handle(array->WasmObject(frame_ix), isolate);
623 wasm_func_index_ = array->WasmFunctionIndex(frame_ix)->value();
624 code_ = handle(array->Code(frame_ix), isolate);
625 offset_ = array->Offset(frame_ix)->value();
626 }
627
628 Handle<Object> WasmStackFrame::GetFunction() const {
629 Handle<Object> obj(Smi::FromInt(wasm_func_index_), isolate_);
630 return obj;
631 }
632
633 Handle<Object> WasmStackFrame::GetFunctionName() {
634 return wasm::GetWasmFunctionNameOrNull(isolate_, wasm_obj_, wasm_func_index_);
635 }
636
637 MaybeHandle<String> WasmStackFrame::ToString() {
638 IncrementalStringBuilder builder(isolate_);
639
640 Handle<Object> name = GetFunctionName();
641 if (name->IsNull(isolate_)) {
642 builder.AppendCString("<WASM UNNAMED>");
643 } else {
644 DCHECK(name->IsString());
645 builder.AppendString(Handle<String>::cast(name));
646 }
647
648 builder.AppendCString(" (<WASM>[");
649
650 Handle<Smi> ix(Smi::FromInt(wasm_func_index_), isolate_);
651 builder.AppendString(isolate_->factory()->NumberToString(ix));
652
653 builder.AppendCString("]+");
654
655 Handle<Object> pos(Smi::FromInt(GetPosition()), isolate_);
656 builder.AppendString(isolate_->factory()->NumberToString(pos));
657 builder.AppendCString(")");
658
659 return builder.Finish();
660 }
661
662 int WasmStackFrame::GetPosition() const {
663 return (offset_ < 0) ? (-1 - offset_) : code_->SourcePosition(offset_);
664 }
665
666 Handle<Object> WasmStackFrame::Null() const {
667 return isolate_->factory()->null_value();
668 }
669
670 FrameArrayIterator::FrameArrayIterator(Isolate* isolate,
671 Handle<FrameArray> array, int frame_ix)
672 : isolate_(isolate), array_(array), next_frame_ix_(frame_ix) {}
673
674 bool FrameArrayIterator::HasNext() const {
675 return (next_frame_ix_ < array_->FrameCount());
676 }
677
678 void FrameArrayIterator::Next() { next_frame_ix_++; }
679
680 StackFrameBase* FrameArrayIterator::Frame() {
681 DCHECK(HasNext());
682 const int flags = array_->Flags(next_frame_ix_)->value();
683 const bool is_js_frame = (flags & FrameArray::kIsWasmFrame) == 0;
684 if (is_js_frame) {
685 js_frame_.FromFrameArray(isolate_, array_, next_frame_ix_);
686 return &js_frame_;
687 } else {
688 wasm_frame_.FromFrameArray(isolate_, array_, next_frame_ix_);
689 return &wasm_frame_;
690 }
691 }
692
693 namespace {
694
695 MaybeHandle<Object> ConstructCallSite(Isolate* isolate,
696 Handle<FrameArray> frame_array,
697 int frame_index) {
698 Handle<JSFunction> target =
699 handle(isolate->native_context()->callsite_function(), isolate);
700
701 Handle<JSObject> obj;
702 ASSIGN_RETURN_ON_EXCEPTION(isolate, obj, JSObject::New(target, target),
703 Object);
704
705 Handle<Symbol> key = isolate->factory()->call_site_frame_array_symbol();
706 RETURN_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes(
707 obj, key, frame_array, DONT_ENUM),
708 Object);
709
710 key = isolate->factory()->call_site_frame_index_symbol();
711 Handle<Object> value(Smi::FromInt(frame_index), isolate);
712 RETURN_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes(
713 obj, key, value, DONT_ENUM),
714 Object);
715
716 return obj;
717 }
718
490 // Convert the raw frames as written by Isolate::CaptureSimpleStackTrace into 719 // Convert the raw frames as written by Isolate::CaptureSimpleStackTrace into
491 // a vector of JS CallSite objects. 720 // a JSArray of JSCallSite objects.
492 MaybeHandle<FixedArray> GetStackFrames(Isolate* isolate, 721 MaybeHandle<JSArray> GetStackFrames(Isolate* isolate,
493 Handle<Object> raw_stack) { 722 Handle<FrameArray> elems) {
494 DCHECK(raw_stack->IsJSArray());
495 Handle<JSArray> raw_stack_array = Handle<JSArray>::cast(raw_stack);
496
497 DCHECK(raw_stack_array->elements()->IsFixedArray());
498 Handle<FrameArray> elems(FrameArray::cast(raw_stack_array->elements()));
499
500 const int frame_count = elems->FrameCount(); 723 const int frame_count = elems->FrameCount();
501 724
502 Handle<FixedArray> frames = isolate->factory()->NewFixedArray(frame_count); 725 Handle<FixedArray> frames = isolate->factory()->NewFixedArray(frame_count);
503 for (int i = 0; i < frame_count; i++) { 726 for (int i = 0; i < frame_count; i++) {
504 const int flags = elems->Flags(i)->value(); 727 Handle<Object> site;
505 Handle<AbstractCode> code(elems->Code(i), isolate); 728 ASSIGN_RETURN_ON_EXCEPTION(isolate, site,
506 Handle<Smi> pc(elems->Offset(i), isolate); 729 ConstructCallSite(isolate, elems, i), JSArray);
507 Handle<Object> strict = 730 frames->set(i, *site);
508 isolate->factory()->ToBoolean(flags & FrameArray::kIsStrict); 731 }
509 732
510 if (elems->IsWasmFrame(i)) { 733 return isolate->factory()->NewJSArrayWithElements(frames);
511 Handle<Object> wasm_obj(elems->WasmObject(i), isolate);
512 Handle<Smi> wasm_fun_ix(elems->WasmFunctionIndex(i), isolate);
513
514 Handle<Object> pos((pc->value() < 0)
515 ? Smi::FromInt(-1 - pc->value())
516 : Smi::FromInt(code->SourcePosition(pc->value())),
517 isolate);
518
519 Handle<Object> callsite;
520 ASSIGN_RETURN_ON_EXCEPTION(
521 isolate, callsite,
522 CallSiteUtils::Construct(isolate, wasm_obj, wasm_fun_ix, pos, strict),
523 FixedArray);
524
525 frames->set(i, *callsite);
526 } else {
527 Handle<Object> recv(elems->Receiver(i), isolate);
528 Handle<Object> fun(elems->Function(i), isolate);
529 Handle<Object> pos(Smi::FromInt(code->SourcePosition(pc->value())),
530 isolate);
531
532 if (flags & FrameArray::kForceConstructor) {
533 recv = handle(isolate->heap()->call_site_constructor_symbol());
534 }
535
536 Handle<Object> callsite;
537 ASSIGN_RETURN_ON_EXCEPTION(
538 isolate, callsite,
539 CallSiteUtils::Construct(isolate, recv, fun, pos, strict),
540 FixedArray);
541
542 frames->set(i, *callsite);
543 }
544 }
545
546 return frames;
547 } 734 }
548 735
549 MaybeHandle<Object> AppendErrorString(Isolate* isolate, Handle<Object> error, 736 MaybeHandle<Object> AppendErrorString(Isolate* isolate, Handle<Object> error,
550 IncrementalStringBuilder* builder) { 737 IncrementalStringBuilder* builder) {
551 MaybeHandle<String> err_str = 738 MaybeHandle<String> err_str =
552 ErrorUtils::ToString(isolate, Handle<Object>::cast(error)); 739 ErrorUtils::ToString(isolate, Handle<Object>::cast(error));
553 if (err_str.is_null()) { 740 if (err_str.is_null()) {
554 // Error.toString threw. Try to return a string representation of the thrown 741 // Error.toString threw. Try to return a string representation of the thrown
555 // exception instead. 742 // exception instead.
556 743
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
593 780
594 DISALLOW_COPY_AND_ASSIGN(PrepareStackTraceScope); 781 DISALLOW_COPY_AND_ASSIGN(PrepareStackTraceScope);
595 }; 782 };
596 783
597 } // namespace 784 } // namespace
598 785
599 // static 786 // static
600 MaybeHandle<Object> ErrorUtils::FormatStackTrace(Isolate* isolate, 787 MaybeHandle<Object> ErrorUtils::FormatStackTrace(Isolate* isolate,
601 Handle<JSObject> error, 788 Handle<JSObject> error,
602 Handle<Object> raw_stack) { 789 Handle<Object> raw_stack) {
603 // Create JS CallSite objects from the raw stack frame array. 790 DCHECK(raw_stack->IsJSArray());
791 Handle<JSArray> raw_stack_array = Handle<JSArray>::cast(raw_stack);
604 792
605 Handle<FixedArray> frames; 793 DCHECK(raw_stack_array->elements()->IsFixedArray());
606 ASSIGN_RETURN_ON_EXCEPTION(isolate, frames, 794 Handle<FrameArray> elems(FrameArray::cast(raw_stack_array->elements()));
607 GetStackFrames(isolate, raw_stack), Object);
608 795
609 // If there's a user-specified "prepareStackFrames" function, call it on the 796 // If there's a user-specified "prepareStackFrames" function, call it on the
610 // frames and use its result. 797 // frames and use its result.
611 798
612 Handle<JSFunction> global_error = isolate->error_function(); 799 Handle<JSFunction> global_error = isolate->error_function();
613 Handle<Object> prepare_stack_trace; 800 Handle<Object> prepare_stack_trace;
614 ASSIGN_RETURN_ON_EXCEPTION( 801 ASSIGN_RETURN_ON_EXCEPTION(
615 isolate, prepare_stack_trace, 802 isolate, prepare_stack_trace,
616 JSFunction::GetProperty(isolate, global_error, "prepareStackTrace"), 803 JSFunction::GetProperty(isolate, global_error, "prepareStackTrace"),
617 Object); 804 Object);
618 805
619 const bool in_recursion = isolate->formatting_stack_trace(); 806 const bool in_recursion = isolate->formatting_stack_trace();
620 if (prepare_stack_trace->IsJSFunction() && !in_recursion) { 807 if (prepare_stack_trace->IsJSFunction() && !in_recursion) {
621 PrepareStackTraceScope scope(isolate); 808 PrepareStackTraceScope scope(isolate);
622 Handle<JSArray> array = isolate->factory()->NewJSArrayWithElements(frames); 809
810 Handle<JSArray> sites;
811 ASSIGN_RETURN_ON_EXCEPTION(isolate, sites, GetStackFrames(isolate, elems),
812 Object);
623 813
624 const int argc = 2; 814 const int argc = 2;
625 ScopedVector<Handle<Object>> argv(argc); 815 ScopedVector<Handle<Object>> argv(argc);
816
626 argv[0] = error; 817 argv[0] = error;
627 argv[1] = array; 818 argv[1] = sites;
628 819
629 Handle<Object> result; 820 Handle<Object> result;
630 ASSIGN_RETURN_ON_EXCEPTION( 821 ASSIGN_RETURN_ON_EXCEPTION(
631 isolate, result, Execution::Call(isolate, prepare_stack_trace, 822 isolate, result, Execution::Call(isolate, prepare_stack_trace,
632 global_error, argc, argv.start()), 823 global_error, argc, argv.start()),
633 Object); 824 Object);
634 825
635 return result; 826 return result;
636 } 827 }
637 828
829 // Otherwise, run our internal formatting logic.
830
638 IncrementalStringBuilder builder(isolate); 831 IncrementalStringBuilder builder(isolate);
639 832
640 RETURN_ON_EXCEPTION(isolate, AppendErrorString(isolate, error, &builder), 833 RETURN_ON_EXCEPTION(isolate, AppendErrorString(isolate, error, &builder),
641 Object); 834 Object);
642 835
643 for (int i = 0; i < frames->length(); i++) { 836 for (FrameArrayIterator it(isolate, elems); it.HasNext(); it.Next()) {
644 builder.AppendCString("\n at "); 837 builder.AppendCString("\n at ");
645 838
646 Handle<Object> frame = FixedArray::get(*frames, i, isolate); 839 StackFrameBase* frame = it.Frame();
647 MaybeHandle<String> maybe_frame_string = 840 MaybeHandle<String> maybe_frame_string = frame->ToString();
648 CallSiteUtils::ToString(isolate, frame);
649 if (maybe_frame_string.is_null()) { 841 if (maybe_frame_string.is_null()) {
650 // CallSite.toString threw. Try to return a string representation of the 842 // CallSite.toString threw. Try to return a string representation of the
651 // thrown exception instead. 843 // thrown exception instead.
652 844
653 DCHECK(isolate->has_pending_exception()); 845 DCHECK(isolate->has_pending_exception());
654 Handle<Object> pending_exception = 846 Handle<Object> pending_exception =
655 handle(isolate->pending_exception(), isolate); 847 handle(isolate->pending_exception(), isolate);
656 isolate->clear_pending_exception(); 848 isolate->clear_pending_exception();
657 849
658 maybe_frame_string = ErrorUtils::ToString(isolate, pending_exception); 850 maybe_frame_string = ErrorUtils::ToString(isolate, pending_exception);
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
905 } 1097 }
906 1098
907 DCHECK(mode != SKIP_UNTIL_SEEN); 1099 DCHECK(mode != SKIP_UNTIL_SEEN);
908 1100
909 Handle<Object> no_caller; 1101 Handle<Object> no_caller;
910 Handle<String> msg = FormatMessage(isolate, template_index, arg0, arg1, arg2); 1102 Handle<String> msg = FormatMessage(isolate, template_index, arg0, arg1, arg2);
911 return ErrorUtils::Construct(isolate, constructor, constructor, msg, mode, 1103 return ErrorUtils::Construct(isolate, constructor, constructor, msg, mode,
912 no_caller, false); 1104 no_caller, false);
913 } 1105 }
914 1106
915 #define SET_CALLSITE_PROPERTY(target, key, value) \
916 RETURN_ON_EXCEPTION( \
917 isolate, JSObject::SetOwnPropertyIgnoreAttributes( \
918 target, isolate->factory()->key(), value, DONT_ENUM), \
919 Object)
920
921 MaybeHandle<Object> CallSiteUtils::Construct(Isolate* isolate,
922 Handle<Object> receiver,
923 Handle<Object> fun,
924 Handle<Object> pos,
925 Handle<Object> strict_mode) {
926 // Create the JS object.
927
928 Handle<JSFunction> target =
929 handle(isolate->native_context()->callsite_function(), isolate);
930
931 Handle<JSObject> obj;
932 ASSIGN_RETURN_ON_EXCEPTION(isolate, obj, JSObject::New(target, target),
933 Object);
934
935 // For wasm frames, receiver is the wasm object and fun is the function index
936 // instead of an actual function.
937 const bool is_wasm_object =
938 receiver->IsJSObject() && wasm::IsWasmObject(JSObject::cast(*receiver));
939 if (!fun->IsJSFunction() && !is_wasm_object) {
940 THROW_NEW_ERROR(isolate,
941 NewTypeError(MessageTemplate::kCallSiteExpectsFunction,
942 Object::TypeOf(isolate, receiver),
943 Object::TypeOf(isolate, fun)),
944 Object);
945 }
946
947 if (is_wasm_object) {
948 DCHECK(fun->IsSmi());
949 DCHECK(wasm::GetNumberOfFunctions(JSObject::cast(*receiver)) >
950 Smi::cast(*fun)->value());
951
952 SET_CALLSITE_PROPERTY(obj, call_site_wasm_obj_symbol, receiver);
953 SET_CALLSITE_PROPERTY(obj, call_site_wasm_func_index_symbol, fun);
954 } else {
955 DCHECK(fun->IsJSFunction());
956 SET_CALLSITE_PROPERTY(obj, call_site_receiver_symbol, receiver);
957 SET_CALLSITE_PROPERTY(obj, call_site_function_symbol, fun);
958 }
959
960 DCHECK(pos->IsSmi());
961 SET_CALLSITE_PROPERTY(obj, call_site_position_symbol, pos);
962 SET_CALLSITE_PROPERTY(
963 obj, call_site_strict_symbol,
964 isolate->factory()->ToBoolean(strict_mode->BooleanValue()));
965
966 return obj;
967 }
968
969 #undef SET_CALLSITE_PROPERTY
970
971 namespace {
972
973 bool IsNonEmptyString(Handle<Object> object) {
974 return (object->IsString() && String::cast(*object)->length() > 0);
975 }
976
977 MaybeHandle<JSObject> AppendWasmToString(Isolate* isolate,
978 Handle<JSObject> recv,
979 CallSite* call_site,
980 IncrementalStringBuilder* builder) {
981 Handle<Object> name = call_site->GetFunctionName();
982 if (name->IsNull(isolate)) {
983 builder->AppendCString("<WASM UNNAMED>");
984 } else {
985 DCHECK(name->IsString());
986 builder->AppendString(Handle<String>::cast(name));
987 }
988
989 builder->AppendCString(" (<WASM>[");
990
991 Handle<String> ix = isolate->factory()->NumberToString(
992 handle(Smi::FromInt(call_site->wasm_func_index()), isolate));
993 builder->AppendString(ix);
994
995 builder->AppendCString("]+");
996
997 Handle<Object> pos;
998 ASSIGN_RETURN_ON_EXCEPTION(
999 isolate, pos, JSObject::GetProperty(
1000 recv, isolate->factory()->call_site_position_symbol()),
1001 JSObject);
1002 DCHECK(pos->IsNumber());
1003 builder->AppendString(isolate->factory()->NumberToString(pos));
1004 builder->AppendCString(")");
1005
1006 return recv;
1007 }
1008
1009 MaybeHandle<JSObject> AppendFileLocation(Isolate* isolate,
1010 Handle<JSObject> recv,
1011 CallSite* call_site,
1012 IncrementalStringBuilder* builder) {
1013 if (call_site->IsNative()) {
1014 builder->AppendCString("native");
1015 return recv;
1016 }
1017
1018 Handle<Object> file_name = call_site->GetScriptNameOrSourceUrl();
1019 if (!file_name->IsString() && call_site->IsEval()) {
1020 Handle<Object> eval_origin = call_site->GetEvalOrigin();
1021 DCHECK(eval_origin->IsString());
1022 builder->AppendString(Handle<String>::cast(eval_origin));
1023 builder->AppendCString(", "); // Expecting source position to follow.
1024 }
1025
1026 if (IsNonEmptyString(file_name)) {
1027 builder->AppendString(Handle<String>::cast(file_name));
1028 } else {
1029 // Source code does not originate from a file and is not native, but we
1030 // can still get the source position inside the source string, e.g. in
1031 // an eval string.
1032 builder->AppendCString("<anonymous>");
1033 }
1034
1035 int line_number = call_site->GetLineNumber();
1036 if (line_number != -1) {
1037 builder->AppendCharacter(':');
1038 Handle<String> line_string = isolate->factory()->NumberToString(
1039 handle(Smi::FromInt(line_number), isolate), isolate);
1040 builder->AppendString(line_string);
1041
1042 int column_number = call_site->GetColumnNumber();
1043 if (column_number != -1) {
1044 builder->AppendCharacter(':');
1045 Handle<String> column_string = isolate->factory()->NumberToString(
1046 handle(Smi::FromInt(column_number), isolate), isolate);
1047 builder->AppendString(column_string);
1048 }
1049 }
1050
1051 return recv;
1052 }
1053
1054 int StringIndexOf(Isolate* isolate, Handle<String> subject,
1055 Handle<String> pattern) {
1056 if (pattern->length() > subject->length()) return -1;
1057 return String::IndexOf(isolate, subject, pattern, 0);
1058 }
1059
1060 // Returns true iff
1061 // 1. the subject ends with '.' + pattern, or
1062 // 2. subject == pattern.
1063 bool StringEndsWithMethodName(Isolate* isolate, Handle<String> subject,
1064 Handle<String> pattern) {
1065 if (String::Equals(subject, pattern)) return true;
1066
1067 FlatStringReader subject_reader(isolate, String::Flatten(subject));
1068 FlatStringReader pattern_reader(isolate, String::Flatten(pattern));
1069
1070 int pattern_index = pattern_reader.length() - 1;
1071 int subject_index = subject_reader.length() - 1;
1072 for (int i = 0; i <= pattern_reader.length(); i++) { // Iterate over len + 1.
1073 if (subject_index < 0) {
1074 return false;
1075 }
1076
1077 const uc32 subject_char = subject_reader.Get(subject_index);
1078 if (i == pattern_reader.length()) {
1079 if (subject_char != '.') return false;
1080 } else if (subject_char != pattern_reader.Get(pattern_index)) {
1081 return false;
1082 }
1083
1084 pattern_index--;
1085 subject_index--;
1086 }
1087
1088 return true;
1089 }
1090
1091 MaybeHandle<JSObject> AppendMethodCall(Isolate* isolate, Handle<JSObject> recv,
1092 CallSite* call_site,
1093 IncrementalStringBuilder* builder) {
1094 Handle<Object> type_name = call_site->GetTypeName();
1095 Handle<Object> method_name = call_site->GetMethodName();
1096 Handle<Object> function_name = call_site->GetFunctionName();
1097
1098 if (IsNonEmptyString(function_name)) {
1099 Handle<String> function_string = Handle<String>::cast(function_name);
1100 if (IsNonEmptyString(type_name)) {
1101 Handle<String> type_string = Handle<String>::cast(type_name);
1102 bool starts_with_type_name =
1103 (StringIndexOf(isolate, function_string, type_string) == 0);
1104 if (!starts_with_type_name) {
1105 builder->AppendString(type_string);
1106 builder->AppendCharacter('.');
1107 }
1108 }
1109 builder->AppendString(function_string);
1110
1111 if (IsNonEmptyString(method_name)) {
1112 Handle<String> method_string = Handle<String>::cast(method_name);
1113 if (!StringEndsWithMethodName(isolate, function_string, method_string)) {
1114 builder->AppendCString(" [as ");
1115 builder->AppendString(method_string);
1116 builder->AppendCharacter(']');
1117 }
1118 }
1119 } else {
1120 builder->AppendString(Handle<String>::cast(type_name));
1121 builder->AppendCharacter('.');
1122 if (IsNonEmptyString(method_name)) {
1123 builder->AppendString(Handle<String>::cast(method_name));
1124 } else {
1125 builder->AppendCString("<anonymous>");
1126 }
1127 }
1128
1129 return recv;
1130 }
1131
1132 } // namespace
1133
1134 MaybeHandle<String> CallSiteUtils::ToString(Isolate* isolate,
1135 Handle<Object> receiver) {
1136 if (!receiver->IsJSObject()) {
1137 THROW_NEW_ERROR(
1138 isolate,
1139 NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
1140 isolate->factory()->NewStringFromAsciiChecked("toString"),
1141 receiver),
1142 String);
1143 }
1144 Handle<JSObject> recv = Handle<JSObject>::cast(receiver);
1145
1146 if (!JSReceiver::HasOwnProperty(
1147 recv, isolate->factory()->call_site_position_symbol())
1148 .FromMaybe(false)) {
1149 THROW_NEW_ERROR(
1150 isolate,
1151 NewTypeError(MessageTemplate::kCallSiteMethod,
1152 isolate->factory()->NewStringFromAsciiChecked("toString")),
1153 String);
1154 }
1155
1156 IncrementalStringBuilder builder(isolate);
1157
1158 CallSite call_site(isolate, recv);
1159 if (call_site.IsWasm()) {
1160 RETURN_ON_EXCEPTION(isolate,
1161 AppendWasmToString(isolate, recv, &call_site, &builder),
1162 String);
1163 RETURN_RESULT(isolate, builder.Finish(), String);
1164 }
1165
1166 DCHECK(!call_site.IsWasm());
1167 Handle<Object> function_name = call_site.GetFunctionName();
1168
1169 const bool is_toplevel = call_site.IsToplevel();
1170 const bool is_constructor = call_site.IsConstructor();
1171 const bool is_method_call = !(is_toplevel || is_constructor);
1172
1173 if (is_method_call) {
1174 RETURN_ON_EXCEPTION(
1175 isolate, AppendMethodCall(isolate, recv, &call_site, &builder), String);
1176 } else if (is_constructor) {
1177 builder.AppendCString("new ");
1178 if (IsNonEmptyString(function_name)) {
1179 builder.AppendString(Handle<String>::cast(function_name));
1180 } else {
1181 builder.AppendCString("<anonymous>");
1182 }
1183 } else if (IsNonEmptyString(function_name)) {
1184 builder.AppendString(Handle<String>::cast(function_name));
1185 } else {
1186 RETURN_ON_EXCEPTION(isolate,
1187 AppendFileLocation(isolate, recv, &call_site, &builder),
1188 String);
1189 RETURN_RESULT(isolate, builder.Finish(), String);
1190 }
1191
1192 builder.AppendCString(" (");
1193 RETURN_ON_EXCEPTION(
1194 isolate, AppendFileLocation(isolate, recv, &call_site, &builder), String);
1195 builder.AppendCString(")");
1196
1197 RETURN_RESULT(isolate, builder.Finish(), String);
1198 }
1199
1200 } // namespace internal 1107 } // namespace internal
1201 } // namespace v8 1108 } // namespace v8
OLDNEW
« no previous file with comments | « src/messages.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698