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 3 // found in the LICENSE file. 4 5 #include "src/messages.h" 6 7 #include <memory> 8 9 #include "src/api.h" 10 #include "src/execution.h" 11 #include "src/isolate-inl.h" 12 #include "src/keys.h" 13 #include "src/string-builder.h" 14 #include "src/wasm/wasm-module.h" 15 #include "src/wasm/wasm-objects.h" 16 17 namespace v8 { 18 namespace internal { 19 20 MessageLocation::MessageLocation(Handle<Script> script, int start_pos, 21 int end_pos) 22 : script_(script), start_pos_(start_pos), end_pos_(end_pos) {} 23 MessageLocation::MessageLocation(Handle<Script> script, int start_pos, 24 int end_pos, Handle<SharedFunctionInfo> shared) 25 : script_(script), 26 start_pos_(start_pos), 27 end_pos_(end_pos), 28 shared_(shared) {} 29 MessageLocation::MessageLocation() : start_pos_(-1), end_pos_(-1) {} 30 31 // If no message listeners have been registered this one is called 32 // by default. 33 void MessageHandler::DefaultMessageReport(Isolate* isolate, 34 const MessageLocation* loc, 35 Handle<Object> message_obj) { 36 std::unique_ptr<char[]> str = GetLocalizedMessage(isolate, message_obj); 37 if (loc == NULL) { 38 PrintF("%s\n", str.get()); 39 } else { 40 HandleScope scope(isolate); 41 Handle<Object> data(loc->script()->name(), isolate); 42 std::unique_ptr<char[]> data_str; 43 if (data->IsString()) 44 data_str = Handle<String>::cast(data)->ToCString(DISALLOW_NULLS); 45 PrintF("%s:%i: %s\n", data_str.get() ? data_str.get() : "<unknown>", 46 loc->start_pos(), str.get()); 47 } 48 } 49 50 Handle<JSMessageObject> MessageHandler::MakeMessageObject( 51 Isolate* isolate, MessageTemplate::Template message, 52 const MessageLocation* location, Handle<Object> argument, 53 Handle<JSArray> stack_frames) { 54 Factory* factory = isolate->factory(); 55 56 int start = -1; 57 int end = -1; 58 Handle<Object> script_handle = factory->undefined_value(); 59 if (location != NULL) { 60 start = location->start_pos(); 61 end = location->end_pos(); 62 script_handle = Script::GetWrapper(location->script()); 63 } else { 64 script_handle = Script::GetWrapper(isolate->factory()->empty_script()); 65 } 66 67 Handle<Object> stack_frames_handle = stack_frames.is_null() 68 ? Handle<Object>::cast(factory->undefined_value()) 69 : Handle<Object>::cast(stack_frames); 70 71 Handle<JSMessageObject> message_obj = factory->NewJSMessageObject( 72 message, argument, start, end, script_handle, stack_frames_handle); 73 74 return message_obj; 75 } 76 77 void MessageHandler::ReportMessage(Isolate* isolate, const MessageLocation* loc, 78 Handle<JSMessageObject> message) { 79 v8::Local<v8::Message> api_message_obj = v8::Utils::MessageToLocal(message); 80 81 if (api_message_obj->ErrorLevel() == v8::Isolate::kMessageError) { 82 // We are calling into embedder's code which can throw exceptions. 83 // Thus we need to save current exception state, reset it to the clean one 84 // and ignore scheduled exceptions callbacks can throw. 85 86 // We pass the exception object into the message handler callback though. 87 Object* exception_object = isolate->heap()->undefined_value(); 88 if (isolate->has_pending_exception()) { 89 exception_object = isolate->pending_exception(); 90 } 91 Handle<Object> exception(exception_object, isolate); 92 93 Isolate::ExceptionScope exception_scope(isolate); 94 isolate->clear_pending_exception(); 95 isolate->set_external_caught_exception(false); 96 97 // Turn the exception on the message into a string if it is an object. 98 if (message->argument()->IsJSObject()) { 99 HandleScope scope(isolate); 100 Handle<Object> argument(message->argument(), isolate); 101 102 MaybeHandle<Object> maybe_stringified; 103 Handle<Object> stringified; 104 // Make sure we don't leak uncaught internally generated Error objects. 105 if (argument->IsJSError()) { 106 maybe_stringified = Object::NoSideEffectsToString(isolate, argument); 107 } else { 108 v8::TryCatch catcher(reinterpret_cast<v8::Isolate*>(isolate)); 109 catcher.SetVerbose(false); 110 catcher.SetCaptureMessage(false); 111 112 maybe_stringified = Object::ToString(isolate, argument); 113 } 114 115 if (!maybe_stringified.ToHandle(&stringified)) { 116 stringified = 117 isolate->factory()->NewStringFromAsciiChecked("exception"); 118 } 119 message->set_argument(*stringified); 120 } 121 122 v8::Local<v8::Value> api_exception_obj = v8::Utils::ToLocal(exception); 123 ReportMessageNoExceptions(isolate, loc, message, api_exception_obj); 124 } else { 125 ReportMessageNoExceptions(isolate, loc, message, v8::Local<v8::Value>()); 126 } 127 } 128 129 void MessageHandler::ReportMessageNoExceptions( 130 Isolate* isolate, const MessageLocation* loc, Handle<Object> message, 131 v8::Local<v8::Value> api_exception_obj) { 132 v8::Local<v8::Message> api_message_obj = v8::Utils::MessageToLocal(message); 133 int error_level = api_message_obj->ErrorLevel(); 134 135 Handle<TemplateList> global_listeners = 136 isolate->factory()->message_listeners(); 137 int global_length = global_listeners->length(); 138 if (global_length == 0) { 139 DefaultMessageReport(isolate, loc, message); 140 if (isolate->has_scheduled_exception()) { 141 isolate->clear_scheduled_exception(); 142 } 143 } else { 144 for (int i = 0; i < global_length; i++) { 145 HandleScope scope(isolate); 146 if (global_listeners->get(i)->IsUndefined(isolate)) continue; 147 FixedArray* listener = FixedArray::cast(global_listeners->get(i)); 148 Foreign* callback_obj = Foreign::cast(listener->get(0)); 149 int32_t message_levels = 150 static_cast<int32_t>(Smi::cast(listener->get(2))->value()); 151 if (!(message_levels & error_level)) { 152 continue; 153 } 154 v8::MessageCallback callback = 155 FUNCTION_CAST<v8::MessageCallback>(callback_obj->foreign_address()); 156 Handle<Object> callback_data(listener->get(1), isolate); 157 { 158 // Do not allow exceptions to propagate. 159 v8::TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate)); 160 callback(api_message_obj, callback_data->IsUndefined(isolate) 161 ? api_exception_obj 162 : v8::Utils::ToLocal(callback_data)); 163 } 164 if (isolate->has_scheduled_exception()) { 165 isolate->clear_scheduled_exception(); 166 } 167 } 168 } 169 } 170 171 172 Handle<String> MessageHandler::GetMessage(Isolate* isolate, 173 Handle<Object> data) { 174 Handle<JSMessageObject> message = Handle<JSMessageObject>::cast(data); 175 Handle<Object> arg = Handle<Object>(message->argument(), isolate); 176 return MessageTemplate::FormatMessage(isolate, message->type(), arg); 177 } 178 179 std::unique_ptr<char[]> MessageHandler::GetLocalizedMessage( 180 Isolate* isolate, Handle<Object> data) { 181 HandleScope scope(isolate); 182 return GetMessage(isolate, data)->ToCString(DISALLOW_NULLS); 183 } 184 185 namespace { 186 187 Object* EvalFromFunctionName(Isolate* isolate, Handle<Script> script) { 188 if (script->eval_from_shared()->IsUndefined(isolate)) 189 return isolate->heap()->undefined_value(); 190 191 Handle<SharedFunctionInfo> shared( 192 SharedFunctionInfo::cast(script->eval_from_shared())); 193 // Find the name of the function calling eval. 194 if (shared->name()->BooleanValue()) { 195 return shared->name(); 196 } 197 198 return shared->inferred_name(); 199 } 200 201 Object* EvalFromScript(Isolate* isolate, Handle<Script> script) { 202 if (script->eval_from_shared()->IsUndefined(isolate)) 203 return isolate->heap()->undefined_value(); 204 205 Handle<SharedFunctionInfo> eval_from_shared( 206 SharedFunctionInfo::cast(script->eval_from_shared())); 207 return eval_from_shared->script()->IsScript() 208 ? eval_from_shared->script() 209 : isolate->heap()->undefined_value(); 210 } 211 212 MaybeHandle<String> FormatEvalOrigin(Isolate* isolate, Handle<Script> script) { 213 Handle<Object> sourceURL(script->GetNameOrSourceURL(), isolate); 214 if (!sourceURL->IsUndefined(isolate)) { 215 DCHECK(sourceURL->IsString()); 216 return Handle<String>::cast(sourceURL); 217 } 218 219 IncrementalStringBuilder builder(isolate); 220 builder.AppendCString("eval at "); 221 222 Handle<Object> eval_from_function_name = 223 handle(EvalFromFunctionName(isolate, script), isolate); 224 if (eval_from_function_name->BooleanValue()) { 225 Handle<String> str; 226 ASSIGN_RETURN_ON_EXCEPTION( 227 isolate, str, Object::ToString(isolate, eval_from_function_name), 228 String); 229 builder.AppendString(str); 230 } else { 231 builder.AppendCString("<anonymous>"); 232 } 233 234 Handle<Object> eval_from_script_obj = 235 handle(EvalFromScript(isolate, script), isolate); 236 if (eval_from_script_obj->IsScript()) { 237 Handle<Script> eval_from_script = 238 Handle<Script>::cast(eval_from_script_obj); 239 builder.AppendCString(" ("); 240 if (eval_from_script->compilation_type() == Script::COMPILATION_TYPE_EVAL) { 241 // Eval script originated from another eval. 242 Handle<String> str; 243 ASSIGN_RETURN_ON_EXCEPTION( 244 isolate, str, FormatEvalOrigin(isolate, eval_from_script), String); 245 builder.AppendString(str); 246 } else { 247 DCHECK(eval_from_script->compilation_type() != 248 Script::COMPILATION_TYPE_EVAL); 249 // eval script originated from "real" source. 250 Handle<Object> name_obj = handle(eval_from_script->name(), isolate); 251 if (eval_from_script->name()->IsString()) { 252 builder.AppendString(Handle<String>::cast(name_obj)); 253 254 Script::PositionInfo info; 255 if (Script::GetPositionInfo(eval_from_script, script->GetEvalPosition(), 256 &info, Script::NO_OFFSET)) { 257 builder.AppendCString(":"); 258 259 Handle<String> str = isolate->factory()->NumberToString( 260 handle(Smi::FromInt(info.line + 1), isolate)); 261 builder.AppendString(str); 262 263 builder.AppendCString(":"); 264 265 str = isolate->factory()->NumberToString( 266 handle(Smi::FromInt(info.column + 1), isolate)); 267 builder.AppendString(str); 268 } 269 } else { 270 DCHECK(!eval_from_script->name()->IsString()); 271 builder.AppendCString("unknown source"); 272 } 273 } 274 builder.AppendCString(")"); 275 } 276 277 Handle<String> result; 278 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, builder.Finish(), String); 279 return result; 280 } 281 282 } // namespace 283 284 Handle<Object> StackFrameBase::GetEvalOrigin() { 285 if (!HasScript()) return isolate_->factory()->undefined_value(); 286 return FormatEvalOrigin(isolate_, GetScript()).ToHandleChecked(); 287 } 288 289 bool StackFrameBase::IsEval() { 290 return HasScript() && 291 GetScript()->compilation_type() == Script::COMPILATION_TYPE_EVAL; 292 } 293 294 void JSStackFrame::FromFrameArray(Isolate* isolate, Handle<FrameArray> array, 295 int frame_ix) { 296 DCHECK(!array->IsWasmFrame(frame_ix)); 297 isolate_ = isolate; 298 receiver_ = handle(array->Receiver(frame_ix), isolate); 299 function_ = handle(array->Function(frame_ix), isolate); 300 code_ = handle(array->Code(frame_ix), isolate); 301 offset_ = array->Offset(frame_ix)->value(); 302 303 const int flags = array->Flags(frame_ix)->value(); 304 force_constructor_ = (flags & FrameArray::kForceConstructor) != 0; 305 is_strict_ = (flags & FrameArray::kIsStrict) != 0; 306 } 307 308 JSStackFrame::JSStackFrame() {} 309 310 JSStackFrame::JSStackFrame(Isolate* isolate, Handle<Object> receiver, 311 Handle<JSFunction> function, 312 Handle<AbstractCode> code, int offset) 313 : StackFrameBase(isolate), 314 receiver_(receiver), 315 function_(function), 316 code_(code), 317 offset_(offset), 318 force_constructor_(false), 319 is_strict_(false) {} 320 321 Handle<Object> JSStackFrame::GetFunction() const { 322 return Handle<Object>::cast(function_); 323 } 324 325 Handle<Object> JSStackFrame::GetFileName() { 326 if (!HasScript()) return isolate_->factory()->null_value(); 327 return handle(GetScript()->name(), isolate_); 328 } 329 330 Handle<Object> JSStackFrame::GetFunctionName() { 331 Handle<String> result = JSFunction::GetName(function_); 332 if (result->length() != 0) return result; 333 334 if (HasScript() && 335 GetScript()->compilation_type() == Script::COMPILATION_TYPE_EVAL) { 336 return isolate_->factory()->eval_string(); 337 } 338 return isolate_->factory()->null_value(); 339 } 340 341 namespace { 342 343 bool CheckMethodName(Isolate* isolate, Handle<JSObject> obj, Handle<Name> name, 344 Handle<JSFunction> fun, 345 LookupIterator::Configuration config) { 346 LookupIterator iter = 347 LookupIterator::PropertyOrElement(isolate, obj, name, config); 348 if (iter.state() == LookupIterator::DATA) { 349 return iter.GetDataValue().is_identical_to(fun); 350 } else if (iter.state() == LookupIterator::ACCESSOR) { 351 Handle<Object> accessors = iter.GetAccessors(); 352 if (accessors->IsAccessorPair()) { 353 Handle<AccessorPair> pair = Handle<AccessorPair>::cast(accessors); 354 return pair->getter() == *fun || pair->setter() == *fun; 355 } 356 } 357 return false; 358 } 359 360 Handle<Object> ScriptNameOrSourceUrl(Handle<Script> script, Isolate* isolate) { 361 Object* name_or_url = script->source_url(); 362 if (!name_or_url->IsString()) name_or_url = script->name(); 363 return handle(name_or_url, isolate); 364 } 365 366 } // namespace 367 368 Handle<Object> JSStackFrame::GetScriptNameOrSourceUrl() { 369 if (!HasScript()) return isolate_->factory()->null_value(); 370 return ScriptNameOrSourceUrl(GetScript(), isolate_); 371 } 372 373 Handle<Object> JSStackFrame::GetMethodName() { 374 if (receiver_->IsNullOrUndefined(isolate_)) { 375 return isolate_->factory()->null_value(); 376 } 377 378 Handle<JSReceiver> receiver = 379 Object::ToObject(isolate_, receiver_).ToHandleChecked(); 380 if (!receiver->IsJSObject()) { 381 return isolate_->factory()->null_value(); 382 } 383 384 Handle<JSObject> obj = Handle<JSObject>::cast(receiver); 385 Handle<Object> function_name(function_->shared()->name(), isolate_); 386 if (function_name->IsString()) { 387 Handle<String> name = Handle<String>::cast(function_name); 388 // ES2015 gives getters and setters name prefixes which must 389 // be stripped to find the property name. 390 if (name->IsUtf8EqualTo(CStrVector("get "), true) || 391 name->IsUtf8EqualTo(CStrVector("set "), true)) { 392 name = isolate_->factory()->NewProperSubString(name, 4, name->length()); 393 } 394 if (CheckMethodName(isolate_, obj, name, function_, 395 LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR)) { 396 return name; 397 } 398 } 399 400 HandleScope outer_scope(isolate_); 401 Handle<Object> result; 402 for (PrototypeIterator iter(isolate_, obj, kStartAtReceiver); !iter.IsAtEnd(); 403 iter.Advance()) { 404 Handle<Object> current = PrototypeIterator::GetCurrent(iter); 405 if (!current->IsJSObject()) break; 406 Handle<JSObject> current_obj = Handle<JSObject>::cast(current); 407 if (current_obj->IsAccessCheckNeeded()) break; 408 Handle<FixedArray> keys = 409 KeyAccumulator::GetOwnEnumPropertyKeys(isolate_, current_obj); 410 for (int i = 0; i < keys->length(); i++) { 411 HandleScope inner_scope(isolate_); 412 if (!keys->get(i)->IsName()) continue; 413 Handle<Name> name_key(Name::cast(keys->get(i)), isolate_); 414 if (!CheckMethodName(isolate_, current_obj, name_key, function_, 415 LookupIterator::OWN_SKIP_INTERCEPTOR)) 416 continue; 417 // Return null in case of duplicates to avoid confusion. 418 if (!result.is_null()) return isolate_->factory()->null_value(); 419 result = inner_scope.CloseAndEscape(name_key); 420 } 421 } 422 423 if (!result.is_null()) return outer_scope.CloseAndEscape(result); 424 return isolate_->factory()->null_value(); 425 } 426 427 Handle<Object> JSStackFrame::GetTypeName() { 428 // TODO(jgruber): Check for strict/constructor here as in 429 // CallSitePrototypeGetThis. 430 431 if (receiver_->IsNullOrUndefined(isolate_)) 432 return isolate_->factory()->null_value(); 433 434 if (receiver_->IsJSProxy()) return isolate_->factory()->Proxy_string(); 435 436 Handle<JSReceiver> receiver_object = 437 Object::ToObject(isolate_, receiver_).ToHandleChecked(); 438 return JSReceiver::GetConstructorName(receiver_object); 439 } 440 441 int JSStackFrame::GetLineNumber() { 442 DCHECK_LE(0, GetPosition()); 443 if (HasScript()) return Script::GetLineNumber(GetScript(), GetPosition()) + 1; 444 return -1; 445 } 446 447 int JSStackFrame::GetColumnNumber() { 448 DCHECK_LE(0, GetPosition()); 449 if (HasScript()) { 450 return Script::GetColumnNumber(GetScript(), GetPosition()) + 1; 451 } 452 return -1; 453 } 454 455 bool JSStackFrame::IsNative() { 456 return HasScript() && GetScript()->type() == Script::TYPE_NATIVE; 457 } 458 459 bool JSStackFrame::IsToplevel() { 460 return receiver_->IsJSGlobalProxy() || receiver_->IsNullOrUndefined(isolate_); 461 } 462 463 bool JSStackFrame::IsConstructor() { 464 if (force_constructor_) return true; 465 if (!receiver_->IsJSObject()) return false; 466 Handle<Object> constructor = 467 JSReceiver::GetDataProperty(Handle<JSObject>::cast(receiver_), 468 isolate_->factory()->constructor_string()); 469 return constructor.is_identical_to(function_); 470 } 471 472 namespace { 473 474 bool IsNonEmptyString(Handle<Object> object) { 475 return (object->IsString() && String::cast(*object)->length() > 0); 476 } 477 478 void AppendFileLocation(Isolate* isolate, StackFrameBase* call_site, 479 IncrementalStringBuilder* builder) { 480 if (call_site->IsNative()) { 481 builder->AppendCString("native"); 482 return; 483 } 484 485 Handle<Object> file_name = call_site->GetScriptNameOrSourceUrl(); 486 if (!file_name->IsString() && call_site->IsEval()) { 487 Handle<Object> eval_origin = call_site->GetEvalOrigin(); 488 DCHECK(eval_origin->IsString()); 489 builder->AppendString(Handle<String>::cast(eval_origin)); 490 builder->AppendCString(", "); // Expecting source position to follow. 491 } 492 493 if (IsNonEmptyString(file_name)) { 494 builder->AppendString(Handle<String>::cast(file_name)); 495 } else { 496 // Source code does not originate from a file and is not native, but we 497 // can still get the source position inside the source string, e.g. in 498 // an eval string. 499 builder->AppendCString("<anonymous>"); 500 } 501 502 int line_number = call_site->GetLineNumber(); 503 if (line_number != -1) { 504 builder->AppendCharacter(':'); 505 Handle<String> line_string = isolate->factory()->NumberToString( 506 handle(Smi::FromInt(line_number), isolate), isolate); 507 builder->AppendString(line_string); 508 509 int column_number = call_site->GetColumnNumber(); 510 if (column_number != -1) { 511 builder->AppendCharacter(':'); 512 Handle<String> column_string = isolate->factory()->NumberToString( 513 handle(Smi::FromInt(column_number), isolate), isolate); 514 builder->AppendString(column_string); 515 } 516 } 517 } 518 519 int StringIndexOf(Isolate* isolate, Handle<String> subject, 520 Handle<String> pattern) { 521 if (pattern->length() > subject->length()) return -1; 522 return String::IndexOf(isolate, subject, pattern, 0); 523 } 524 525 // Returns true iff 526 // 1. the subject ends with '.' + pattern, or 527 // 2. subject == pattern. 528 bool StringEndsWithMethodName(Isolate* isolate, Handle<String> subject, 529 Handle<String> pattern) { 530 if (String::Equals(subject, pattern)) return true; 531 532 FlatStringReader subject_reader(isolate, String::Flatten(subject)); 533 FlatStringReader pattern_reader(isolate, String::Flatten(pattern)); 534 535 int pattern_index = pattern_reader.length() - 1; 536 int subject_index = subject_reader.length() - 1; 537 for (int i = 0; i <= pattern_reader.length(); i++) { // Iterate over len + 1. 538 if (subject_index < 0) { 539 return false; 540 } 541 542 const uc32 subject_char = subject_reader.Get(subject_index); 543 if (i == pattern_reader.length()) { 544 if (subject_char != '.') return false; 545 } else if (subject_char != pattern_reader.Get(pattern_index)) { 546 return false; 547 } 548 549 pattern_index--; 550 subject_index--; 551 } 552 553 return true; 554 } 555 556 void AppendMethodCall(Isolate* isolate, JSStackFrame* call_site, 557 IncrementalStringBuilder* builder) { 558 Handle<Object> type_name = call_site->GetTypeName(); 559 Handle<Object> method_name = call_site->GetMethodName(); 560 Handle<Object> function_name = call_site->GetFunctionName(); 561 562 if (IsNonEmptyString(function_name)) { 563 Handle<String> function_string = Handle<String>::cast(function_name); 564 if (IsNonEmptyString(type_name)) { 565 Handle<String> type_string = Handle<String>::cast(type_name); 566 bool starts_with_type_name = 567 (StringIndexOf(isolate, function_string, type_string) == 0); 568 if (!starts_with_type_name) { 569 builder->AppendString(type_string); 570 builder->AppendCharacter('.'); 571 } 572 } 573 builder->AppendString(function_string); 574 575 if (IsNonEmptyString(method_name)) { 576 Handle<String> method_string = Handle<String>::cast(method_name); 577 if (!StringEndsWithMethodName(isolate, function_string, method_string)) { 578 builder->AppendCString(" [as "); 579 builder->AppendString(method_string); 580 builder->AppendCharacter(']'); 581 } 582 } 583 } else { 584 builder->AppendString(Handle<String>::cast(type_name)); 585 builder->AppendCharacter('.'); 586 if (IsNonEmptyString(method_name)) { 587 builder->AppendString(Handle<String>::cast(method_name)); 588 } else { 589 builder->AppendCString("<anonymous>"); 590 } 591 } 592 } 593 594 } // namespace 595 596 MaybeHandle<String> JSStackFrame::ToString() { 597 IncrementalStringBuilder builder(isolate_); 598 599 Handle<Object> function_name = GetFunctionName(); 600 601 const bool is_toplevel = IsToplevel(); 602 const bool is_constructor = IsConstructor(); 603 const bool is_method_call = !(is_toplevel || is_constructor); 604 605 if (is_method_call) { 606 AppendMethodCall(isolate_, this, &builder); 607 } else if (is_constructor) { 608 builder.AppendCString("new "); 609 if (IsNonEmptyString(function_name)) { 610 builder.AppendString(Handle<String>::cast(function_name)); 611 } else { 612 builder.AppendCString("<anonymous>"); 613 } 614 } else if (IsNonEmptyString(function_name)) { 615 builder.AppendString(Handle<String>::cast(function_name)); 616 } else { 617 AppendFileLocation(isolate_, this, &builder); 618 return builder.Finish(); 619 } 620 621 builder.AppendCString(" ("); 622 AppendFileLocation(isolate_, this, &builder); 623 builder.AppendCString(")"); 624 625 return builder.Finish(); 626 } 627 628 int JSStackFrame::GetPosition() const { return code_->SourcePosition(offset_); } 629 630 bool JSStackFrame::HasScript() const { 631 return function_->shared()->script()->IsScript(); 632 } 633 634 Handle<Script> JSStackFrame::GetScript() const { 635 return handle(Script::cast(function_->shared()->script()), isolate_); 636 } 637 638 WasmStackFrame::WasmStackFrame() {} 639 640 void WasmStackFrame::FromFrameArray(Isolate* isolate, Handle<FrameArray> array, 641 int frame_ix) { 642 // This function is called for both wasm and asm.js->wasm frames. 643 DCHECK(array->IsWasmFrame(frame_ix) || array->IsAsmJsWasmFrame(frame_ix)); 644 isolate_ = isolate; 645 wasm_instance_ = handle(array->WasmInstance(frame_ix), isolate); 646 wasm_func_index_ = array->WasmFunctionIndex(frame_ix)->value(); 647 code_ = handle(array->Code(frame_ix), isolate); 648 offset_ = array->Offset(frame_ix)->value(); 649 } 650 651 Handle<Object> WasmStackFrame::GetFunction() const { 652 Handle<Object> obj(Smi::FromInt(wasm_func_index_), isolate_); 653 return obj; 654 } 655 656 Handle<Object> WasmStackFrame::GetFunctionName() { 657 Handle<Object> name; 658 Handle<WasmCompiledModule> compiled_module( 659 Handle<WasmInstanceObject>::cast(wasm_instance_)->compiled_module(), 660 isolate_); 661 if (!WasmCompiledModule::GetFunctionNameOrNull(isolate_, compiled_module, 662 wasm_func_index_) 663 .ToHandle(&name)) { 664 name = isolate_->factory()->null_value(); 665 } 666 return name; 667 } 668 669 MaybeHandle<String> WasmStackFrame::ToString() { 670 IncrementalStringBuilder builder(isolate_); 671 672 Handle<Object> name = GetFunctionName(); 673 if (name->IsNull(isolate_)) { 674 builder.AppendCString("<WASM UNNAMED>"); 675 } else { 676 DCHECK(name->IsString()); 677 builder.AppendString(Handle<String>::cast(name)); 678 } 679 680 builder.AppendCString(" (<WASM>["); 681 682 Handle<Smi> ix(Smi::FromInt(wasm_func_index_), isolate_); 683 builder.AppendString(isolate_->factory()->NumberToString(ix)); 684 685 builder.AppendCString("]+"); 686 687 Handle<Object> pos(Smi::FromInt(GetPosition()), isolate_); 688 builder.AppendString(isolate_->factory()->NumberToString(pos)); 689 builder.AppendCString(")"); 690 691 return builder.Finish(); 692 } 693 694 int WasmStackFrame::GetPosition() const { 695 // TODO(wasm): Clean this up (bug 5007). 696 return (offset_ < 0) ? (-1 - offset_) : code_->SourcePosition(offset_); 697 } 698 699 Handle<Object> WasmStackFrame::Null() const { 700 return isolate_->factory()->null_value(); 701 } 702 703 bool WasmStackFrame::HasScript() const { return true; } 704 705 Handle<Script> WasmStackFrame::GetScript() const { 706 return handle( 707 WasmInstanceObject::cast(*wasm_instance_)->compiled_module()->script(), 708 isolate_); 709 } 710 711 AsmJsWasmStackFrame::AsmJsWasmStackFrame() {} 712 713 void AsmJsWasmStackFrame::FromFrameArray(Isolate* isolate, 714 Handle<FrameArray> array, 715 int frame_ix) { 716 DCHECK(array->IsAsmJsWasmFrame(frame_ix)); 717 WasmStackFrame::FromFrameArray(isolate, array, frame_ix); 718 is_at_number_conversion_ = 719 array->Flags(frame_ix)->value() & FrameArray::kAsmJsAtNumberConversion; 720 } 721 722 Handle<Object> AsmJsWasmStackFrame::GetReceiver() const { 723 return isolate_->global_proxy(); 724 } 725 726 Handle<Object> AsmJsWasmStackFrame::GetFunction() const { 727 // TODO(clemensh): Return lazily created JSFunction. 728 return Null(); 729 } 730 731 Handle<Object> AsmJsWasmStackFrame::GetFileName() { 732 Handle<Script> script = 733 wasm::GetScript(Handle<JSObject>::cast(wasm_instance_)); 734 DCHECK_EQ(Script::TYPE_NORMAL, script->type()); 735 return handle(script->name(), isolate_); 736 } 737 738 Handle<Object> AsmJsWasmStackFrame::GetScriptNameOrSourceUrl() { 739 Handle<Script> script = 740 wasm::GetScript(Handle<JSObject>::cast(wasm_instance_)); 741 DCHECK_EQ(Script::TYPE_NORMAL, script->type()); 742 return ScriptNameOrSourceUrl(script, isolate_); 743 } 744 745 int AsmJsWasmStackFrame::GetPosition() const { 746 DCHECK_LE(0, offset_); 747 int byte_offset = code_->SourcePosition(offset_); 748 Handle<WasmCompiledModule> compiled_module( 749 WasmInstanceObject::cast(*wasm_instance_)->compiled_module(), isolate_); 750 DCHECK_LE(0, byte_offset); 751 return WasmCompiledModule::GetAsmJsSourcePosition( 752 compiled_module, wasm_func_index_, static_cast<uint32_t>(byte_offset), 753 is_at_number_conversion_); 754 } 755 756 int AsmJsWasmStackFrame::GetLineNumber() { 757 DCHECK_LE(0, GetPosition()); 758 Handle<Script> script = 759 wasm::GetScript(Handle<JSObject>::cast(wasm_instance_)); 760 DCHECK_EQ(Script::TYPE_NORMAL, script->type()); 761 return Script::GetLineNumber(script, GetPosition()) + 1; 762 } 763 764 int AsmJsWasmStackFrame::GetColumnNumber() { 765 DCHECK_LE(0, GetPosition()); 766 Handle<Script> script = 767 wasm::GetScript(Handle<JSObject>::cast(wasm_instance_)); 768 DCHECK_EQ(Script::TYPE_NORMAL, script->type()); 769 return Script::GetColumnNumber(script, GetPosition()) + 1; 770 } 771 772 MaybeHandle<String> AsmJsWasmStackFrame::ToString() { 773 // The string should look exactly as the respective javascript frame string. 774 // Keep this method in line to JSStackFrame::ToString(). 775 776 IncrementalStringBuilder builder(isolate_); 777 778 Handle<Object> function_name = GetFunctionName(); 779 780 if (IsNonEmptyString(function_name)) { 781 builder.AppendString(Handle<String>::cast(function_name)); 782 builder.AppendCString(" ("); 783 } 784 785 AppendFileLocation(isolate_, this, &builder); 786 787 if (IsNonEmptyString(function_name)) builder.AppendCString(")"); 788 789 return builder.Finish(); 790 } 791 792 FrameArrayIterator::FrameArrayIterator(Isolate* isolate, 793 Handle<FrameArray> array, int frame_ix) 794 : isolate_(isolate), array_(array), next_frame_ix_(frame_ix) {} 795 796 bool FrameArrayIterator::HasNext() const { 797 return (next_frame_ix_ < array_->FrameCount()); 798 } 799 800 void FrameArrayIterator::Next() { next_frame_ix_++; } 801 802 StackFrameBase* FrameArrayIterator::Frame() { 803 DCHECK(HasNext()); 804 const int flags = array_->Flags(next_frame_ix_)->value(); 805 switch (flags & (FrameArray::kIsWasmFrame | FrameArray::kIsAsmJsWasmFrame)) { 806 case 0: 807 // JavaScript Frame. 808 js_frame_.FromFrameArray(isolate_, array_, next_frame_ix_); 809 return &js_frame_; 810 case FrameArray::kIsWasmFrame: 811 // Wasm Frame; 812 wasm_frame_.FromFrameArray(isolate_, array_, next_frame_ix_); 813 return &wasm_frame_; 814 case FrameArray::kIsAsmJsWasmFrame: 815 // Asm.js Wasm Frame: 816 asm_wasm_frame_.FromFrameArray(isolate_, array_, next_frame_ix_); 817 return &asm_wasm_frame_; 818 default: 819 UNREACHABLE(); 820 return nullptr; 821 } 822 } 823 824 namespace { 825 826 MaybeHandle<Object> ConstructCallSite(Isolate* isolate, 827 Handle<FrameArray> frame_array, 828 int frame_index) { 829 Handle<JSFunction> target = 830 handle(isolate->native_context()->callsite_function(), isolate); 831 832 Handle<JSObject> obj; 833 ASSIGN_RETURN_ON_EXCEPTION(isolate, obj, JSObject::New(target, target), 834 Object); 835 836 Handle<Symbol> key = isolate->factory()->call_site_frame_array_symbol(); 837 RETURN_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes( 838 obj, key, frame_array, DONT_ENUM), 839 Object); 840 841 key = isolate->factory()->call_site_frame_index_symbol(); 842 Handle<Object> value(Smi::FromInt(frame_index), isolate); 843 RETURN_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes( 844 obj, key, value, DONT_ENUM), 845 Object); 846 847 return obj; 848 } 849 850 // Convert the raw frames as written by Isolate::CaptureSimpleStackTrace into 851 // a JSArray of JSCallSite objects. 852 MaybeHandle<JSArray> GetStackFrames(Isolate* isolate, 853 Handle<FrameArray> elems) { 854 const int frame_count = elems->FrameCount(); 855 856 Handle<FixedArray> frames = isolate->factory()->NewFixedArray(frame_count); 857 for (int i = 0; i < frame_count; i++) { 858 Handle<Object> site; 859 ASSIGN_RETURN_ON_EXCEPTION(isolate, site, 860 ConstructCallSite(isolate, elems, i), JSArray); 861 frames->set(i, *site); 862 } 863 864 return isolate->factory()->NewJSArrayWithElements(frames); 865 } 866 867 MaybeHandle<Object> AppendErrorString(Isolate* isolate, Handle<Object> error, 868 IncrementalStringBuilder* builder) { 869 MaybeHandle<String> err_str = 870 ErrorUtils::ToString(isolate, Handle<Object>::cast(error)); 871 if (err_str.is_null()) { 872 // Error.toString threw. Try to return a string representation of the thrown 873 // exception instead. 874 875 DCHECK(isolate->has_pending_exception()); 876 Handle<Object> pending_exception = 877 handle(isolate->pending_exception(), isolate); 878 isolate->clear_pending_exception(); 879 880 err_str = ErrorUtils::ToString(isolate, pending_exception); 881 if (err_str.is_null()) { 882 // Formatting the thrown exception threw again, give up. 883 DCHECK(isolate->has_pending_exception()); 884 isolate->clear_pending_exception(); 885 886 builder->AppendCString("<error>"); 887 } else { 888 // Formatted thrown exception successfully, append it. 889 builder->AppendCString("<error: "); 890 builder->AppendString(err_str.ToHandleChecked()); 891 builder->AppendCharacter('>'); 892 } 893 } else { 894 builder->AppendString(err_str.ToHandleChecked()); 895 } 896 897 return error; 898 } 899 900 class PrepareStackTraceScope { 901 public: 902 explicit PrepareStackTraceScope(Isolate* isolate) : isolate_(isolate) { 903 DCHECK(!isolate_->formatting_stack_trace()); 904 isolate_->set_formatting_stack_trace(true); 905 } 906 907 ~PrepareStackTraceScope() { isolate_->set_formatting_stack_trace(false); } 908 909 private: 910 Isolate* isolate_; 911 912 DISALLOW_COPY_AND_ASSIGN(PrepareStackTraceScope); 913 }; 914 915 } // namespace 916 917 // static 918 MaybeHandle<Object> ErrorUtils::FormatStackTrace(Isolate* isolate, 919 Handle<JSObject> error, 920 Handle<Object> raw_stack) { 921 DCHECK(raw_stack->IsJSArray()); 922 Handle<JSArray> raw_stack_array = Handle<JSArray>::cast(raw_stack); 923 924 DCHECK(raw_stack_array->elements()->IsFixedArray()); 925 Handle<FrameArray> elems(FrameArray::cast(raw_stack_array->elements())); 926 927 // If there's a user-specified "prepareStackFrames" function, call it on the 928 // frames and use its result. 929 930 Handle<JSFunction> global_error = isolate->error_function(); 931 Handle<Object> prepare_stack_trace; 932 ASSIGN_RETURN_ON_EXCEPTION( 933 isolate, prepare_stack_trace, 934 JSFunction::GetProperty(isolate, global_error, "prepareStackTrace"), 935 Object); 936 937 const bool in_recursion = isolate->formatting_stack_trace(); 938 if (prepare_stack_trace->IsJSFunction() && !in_recursion) { 939 PrepareStackTraceScope scope(isolate); 940 941 Handle<JSArray> sites; 942 ASSIGN_RETURN_ON_EXCEPTION(isolate, sites, GetStackFrames(isolate, elems), 943 Object); 944 945 const int argc = 2; 946 ScopedVector<Handle<Object>> argv(argc); 947 948 argv[0] = error; 949 argv[1] = sites; 950 951 Handle<Object> result; 952 ASSIGN_RETURN_ON_EXCEPTION( 953 isolate, result, Execution::Call(isolate, prepare_stack_trace, 954 global_error, argc, argv.start()), 955 Object); 956 957 return result; 958 } 959 960 // Otherwise, run our internal formatting logic. 961 962 IncrementalStringBuilder builder(isolate); 963 964 RETURN_ON_EXCEPTION(isolate, AppendErrorString(isolate, error, &builder), 965 Object); 966 967 for (FrameArrayIterator it(isolate, elems); it.HasNext(); it.Next()) { 968 builder.AppendCString("\n at "); 969 970 StackFrameBase* frame = it.Frame(); 971 MaybeHandle<String> maybe_frame_string = frame->ToString(); 972 if (maybe_frame_string.is_null()) { 973 // CallSite.toString threw. Try to return a string representation of the 974 // thrown exception instead. 975 976 DCHECK(isolate->has_pending_exception()); 977 Handle<Object> pending_exception = 978 handle(isolate->pending_exception(), isolate); 979 isolate->clear_pending_exception(); 980 981 maybe_frame_string = ErrorUtils::ToString(isolate, pending_exception); 982 if (maybe_frame_string.is_null()) { 983 // Formatting the thrown exception threw again, give up. 984 985 builder.AppendCString("<error>"); 986 } else { 987 // Formatted thrown exception successfully, append it. 988 builder.AppendCString("<error: "); 989 builder.AppendString(maybe_frame_string.ToHandleChecked()); 990 builder.AppendCString("<error>"); 991 } 992 } else { 993 // CallSite.toString completed without throwing. 994 builder.AppendString(maybe_frame_string.ToHandleChecked()); 995 } 996 } 997 998 return builder.Finish(); 999 } 1000 1001 Handle<String> MessageTemplate::FormatMessage(Isolate* isolate, 1002 int template_index, 1003 Handle<Object> arg) { 1004 Factory* factory = isolate->factory(); 1005 Handle<String> result_string = Object::NoSideEffectsToString(isolate, arg); 1006 MaybeHandle<String> maybe_result_string = MessageTemplate::FormatMessage( 1007 template_index, result_string, factory->empty_string(), 1008 factory->empty_string()); 1009 if (!maybe_result_string.ToHandle(&result_string)) { 1010 return factory->InternalizeOneByteString(STATIC_CHAR_VECTOR("<error>")); 1011 } 1012 // A string that has been obtained from JS code in this way is 1013 // likely to be a complicated ConsString of some sort. We flatten it 1014 // here to improve the efficiency of converting it to a C string and 1015 // other operations that are likely to take place (see GetLocalizedMessage 1016 // for example). 1017 return String::Flatten(result_string); 1018 } 1019 1020 1021 const char* MessageTemplate::TemplateString(int template_index) { 1022 switch (template_index) { 1023 #define CASE(NAME, STRING) \ 1024 case k##NAME: \ 1025 return STRING; 1026 MESSAGE_TEMPLATES(CASE) 1027 #undef CASE 1028 case kLastMessage: 1029 default: 1030 return NULL; 1031 } 1032 } 1033 1034 1035 MaybeHandle<String> MessageTemplate::FormatMessage(int template_index, 1036 Handle<String> arg0, 1037 Handle<String> arg1, 1038 Handle<String> arg2) { 1039 Isolate* isolate = arg0->GetIsolate(); 1040 const char* template_string = TemplateString(template_index); 1041 if (template_string == NULL) { 1042 isolate->ThrowIllegalOperation(); 1043 return MaybeHandle<String>(); 1044 } 1045 1046 IncrementalStringBuilder builder(isolate); 1047 1048 unsigned int i = 0; 1049 Handle<String> args[] = {arg0, arg1, arg2}; 1050 for (const char* c = template_string; *c != '\0'; c++) { 1051 if (*c == '%') { 1052 // %% results in verbatim %. 1053 if (*(c + 1) == '%') { 1054 c++; 1055 builder.AppendCharacter('%'); 1056 } else { 1057 DCHECK(i < arraysize(args)); 1058 Handle<String> arg = args[i++]; 1059 builder.AppendString(arg); 1060 } 1061 } else { 1062 builder.AppendCharacter(*c); 1063 } 1064 } 1065 1066 return builder.Finish(); 1067 } 1068 1069 MaybeHandle<Object> ErrorUtils::Construct( 1070 Isolate* isolate, Handle<JSFunction> target, Handle<Object> new_target, 1071 Handle<Object> message, FrameSkipMode mode, Handle<Object> caller, 1072 bool suppress_detailed_trace) { 1073 // 1. If NewTarget is undefined, let newTarget be the active function object, 1074 // else let newTarget be NewTarget. 1075 1076 Handle<JSReceiver> new_target_recv = 1077 new_target->IsJSReceiver() ? Handle<JSReceiver>::cast(new_target) 1078 : Handle<JSReceiver>::cast(target); 1079 1080 // 2. Let O be ? OrdinaryCreateFromConstructor(newTarget, "%ErrorPrototype%", 1081 // [[ErrorData]] ). 1082 Handle<JSObject> err; 1083 ASSIGN_RETURN_ON_EXCEPTION(isolate, err, 1084 JSObject::New(target, new_target_recv), Object); 1085 1086 // 3. If message is not undefined, then 1087 // a. Let msg be ? ToString(message). 1088 // b. Let msgDesc be the PropertyDescriptor{[[Value]]: msg, [[Writable]]: 1089 // true, [[Enumerable]]: false, [[Configurable]]: true}. 1090 // c. Perform ! DefinePropertyOrThrow(O, "message", msgDesc). 1091 // 4. Return O. 1092 1093 if (!message->IsUndefined(isolate)) { 1094 Handle<String> msg_string; 1095 ASSIGN_RETURN_ON_EXCEPTION(isolate, msg_string, 1096 Object::ToString(isolate, message), Object); 1097 RETURN_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes( 1098 err, isolate->factory()->message_string(), 1099 msg_string, DONT_ENUM), 1100 Object); 1101 } 1102 1103 // Optionally capture a more detailed stack trace for the message. 1104 if (!suppress_detailed_trace) { 1105 RETURN_ON_EXCEPTION(isolate, isolate->CaptureAndSetDetailedStackTrace(err), 1106 Object); 1107 } 1108 1109 // Capture a simple stack trace for the stack property. 1110 RETURN_ON_EXCEPTION(isolate, 1111 isolate->CaptureAndSetSimpleStackTrace(err, mode, caller), 1112 Object); 1113 1114 return err; 1115 } 1116 1117 namespace { 1118 1119 MaybeHandle<String> GetStringPropertyOrDefault(Isolate* isolate, 1120 Handle<JSReceiver> recv, 1121 Handle<String> key, 1122 Handle<String> default_str) { 1123 Handle<Object> obj; 1124 ASSIGN_RETURN_ON_EXCEPTION(isolate, obj, JSObject::GetProperty(recv, key), 1125 String); 1126 1127 Handle<String> str; 1128 if (obj->IsUndefined(isolate)) { 1129 str = default_str; 1130 } else { 1131 ASSIGN_RETURN_ON_EXCEPTION(isolate, str, Object::ToString(isolate, obj), 1132 String); 1133 } 1134 1135 return str; 1136 } 1137 1138 } // namespace 1139 1140 // ES6 section 19.5.3.4 Error.prototype.toString ( ) 1141 MaybeHandle<String> ErrorUtils::ToString(Isolate* isolate, 1142 Handle<Object> receiver) { 1143 // 1. Let O be the this value. 1144 // 2. If Type(O) is not Object, throw a TypeError exception. 1145 if (!receiver->IsJSReceiver()) { 1146 return isolate->Throw<String>(isolate->factory()->NewTypeError( 1147 MessageTemplate::kIncompatibleMethodReceiver, 1148 isolate->factory()->NewStringFromAsciiChecked( 1149 "Error.prototype.toString"), 1150 receiver)); 1151 } 1152 Handle<JSReceiver> recv = Handle<JSReceiver>::cast(receiver); 1153 1154 // 3. Let name be ? Get(O, "name"). 1155 // 4. If name is undefined, let name be "Error"; otherwise let name be 1156 // ? ToString(name). 1157 Handle<String> name_key = isolate->factory()->name_string(); 1158 Handle<String> name_default = isolate->factory()->Error_string(); 1159 Handle<String> name; 1160 ASSIGN_RETURN_ON_EXCEPTION( 1161 isolate, name, 1162 GetStringPropertyOrDefault(isolate, recv, name_key, name_default), 1163 String); 1164 1165 // 5. Let msg be ? Get(O, "message"). 1166 // 6. If msg is undefined, let msg be the empty String; otherwise let msg be 1167 // ? ToString(msg). 1168 Handle<String> msg_key = isolate->factory()->message_string(); 1169 Handle<String> msg_default = isolate->factory()->empty_string(); 1170 Handle<String> msg; 1171 ASSIGN_RETURN_ON_EXCEPTION( 1172 isolate, msg, 1173 GetStringPropertyOrDefault(isolate, recv, msg_key, msg_default), String); 1174 1175 // 7. If name is the empty String, return msg. 1176 // 8. If msg is the empty String, return name. 1177 if (name->length() == 0) return msg; 1178 if (msg->length() == 0) return name; 1179 1180 // 9. Return the result of concatenating name, the code unit 0x003A (COLON), 1181 // the code unit 0x0020 (SPACE), and msg. 1182 IncrementalStringBuilder builder(isolate); 1183 builder.AppendString(name); 1184 builder.AppendCString(": "); 1185 builder.AppendString(msg); 1186 1187 Handle<String> result; 1188 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, builder.Finish(), String); 1189 return result; 1190 } 1191 1192 namespace { 1193 1194 Handle<String> FormatMessage(Isolate* isolate, int template_index, 1195 Handle<Object> arg0, Handle<Object> arg1, 1196 Handle<Object> arg2) { 1197 Handle<String> arg0_str = Object::NoSideEffectsToString(isolate, arg0); 1198 Handle<String> arg1_str = Object::NoSideEffectsToString(isolate, arg1); 1199 Handle<String> arg2_str = Object::NoSideEffectsToString(isolate, arg2); 1200 1201 isolate->native_context()->IncrementErrorsThrown(); 1202 1203 Handle<String> msg; 1204 if (!MessageTemplate::FormatMessage(template_index, arg0_str, arg1_str, 1205 arg2_str) 1206 .ToHandle(&msg)) { 1207 DCHECK(isolate->has_pending_exception()); 1208 isolate->clear_pending_exception(); 1209 return isolate->factory()->NewStringFromAsciiChecked("<error>"); 1210 } 1211 1212 return msg; 1213 } 1214 1215 } // namespace 1216 1217 // static 1218 MaybeHandle<Object> ErrorUtils::MakeGenericError( 1219 Isolate* isolate, Handle<JSFunction> constructor, int template_index, 1220 Handle<Object> arg0, Handle<Object> arg1, Handle<Object> arg2, 1221 FrameSkipMode mode) { 1222 if (FLAG_clear_exceptions_on_js_entry) { 1223 // This function used to be implemented in JavaScript, and JSEntryStub 1224 // clears 1225 // any pending exceptions - so whenever we'd call this from C++, pending 1226 // exceptions would be cleared. Preserve this behavior. 1227 isolate->clear_pending_exception(); 1228 } 1229 1230 DCHECK(mode != SKIP_UNTIL_SEEN); 1231 1232 Handle<Object> no_caller; 1233 Handle<String> msg = FormatMessage(isolate, template_index, arg0, arg1, arg2); 1234 return ErrorUtils::Construct(isolate, constructor, constructor, msg, mode, 1235 no_caller, false); 1236 } 1237 1238 } // namespace internal 1239 } // namespace v8 1240