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