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