1 // Copyright 2015 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/pending-compilation-error-handler.h"
6
7 #include "src/ast/ast-value-factory.h"
8 #include "src/debug/debug.h"
9 #include "src/handles.h"
10 #include "src/isolate.h"
11 #include "src/messages.h"
12 #include "src/objects-inl.h"
13
14 namespace v8 {
15 namespace internal {
16
ArgumentString(Isolate * isolate) const17 Handle<String> PendingCompilationErrorHandler::MessageDetails::ArgumentString(
18 Isolate* isolate) const {
19 if (arg_ != nullptr) return arg_->string();
20 if (char_arg_ != nullptr) {
21 return isolate->factory()
22 ->NewStringFromUtf8(CStrVector(char_arg_))
23 .ToHandleChecked();
24 }
25 return isolate->factory()->undefined_string();
26 }
27
GetLocation(Handle<Script> script) const28 MessageLocation PendingCompilationErrorHandler::MessageDetails::GetLocation(
29 Handle<Script> script) const {
30 return MessageLocation(script, start_position_, end_position_);
31 }
32
ReportMessageAt(int start_position,int end_position,MessageTemplate::Template message,const char * arg,ParseErrorType error_type)33 void PendingCompilationErrorHandler::ReportMessageAt(
34 int start_position, int end_position, MessageTemplate::Template message,
35 const char* arg, ParseErrorType error_type) {
36 if (has_pending_error_) return;
37 has_pending_error_ = true;
38
39 error_details_ =
40 MessageDetails(start_position, end_position, message, nullptr, arg);
41 error_type_ = error_type;
42 }
43
ReportMessageAt(int start_position,int end_position,MessageTemplate::Template message,const AstRawString * arg,ParseErrorType error_type)44 void PendingCompilationErrorHandler::ReportMessageAt(
45 int start_position, int end_position, MessageTemplate::Template message,
46 const AstRawString* arg, ParseErrorType error_type) {
47 if (has_pending_error_) return;
48 has_pending_error_ = true;
49
50 error_details_ =
51 MessageDetails(start_position, end_position, message, arg, nullptr);
52 error_type_ = error_type;
53 }
54
ReportWarningAt(int start_position,int end_position,MessageTemplate::Template message,const char * arg)55 void PendingCompilationErrorHandler::ReportWarningAt(
56 int start_position, int end_position, MessageTemplate::Template message,
57 const char* arg) {
58 warning_messages_.emplace_front(
59 MessageDetails(start_position, end_position, message, nullptr, arg));
60 }
61
ReportWarnings(Isolate * isolate,Handle<Script> script)62 void PendingCompilationErrorHandler::ReportWarnings(Isolate* isolate,
63 Handle<Script> script) {
64 DCHECK(!has_pending_error());
65
66 for (const MessageDetails& warning : warning_messages_) {
67 MessageLocation location = warning.GetLocation(script);
68 Handle<String> argument = warning.ArgumentString(isolate);
69 Handle<JSMessageObject> message =
70 MessageHandler::MakeMessageObject(isolate, warning.message(), &location,
71 argument, Handle<FixedArray>::null());
72 message->set_error_level(v8::Isolate::kMessageWarning);
73 MessageHandler::ReportMessage(isolate, &location, message);
74 }
75 }
76
ReportErrors(Isolate * isolate,Handle<Script> script,AstValueFactory * ast_value_factory)77 void PendingCompilationErrorHandler::ReportErrors(
78 Isolate* isolate, Handle<Script> script,
79 AstValueFactory* ast_value_factory) {
80 if (stack_overflow()) {
81 isolate->StackOverflow();
82 } else {
83 DCHECK(has_pending_error());
84 // Internalize ast values for throwing the pending error.
85 ast_value_factory->Internalize(isolate);
86 ThrowPendingError(isolate, script);
87 }
88 }
89
ThrowPendingError(Isolate * isolate,Handle<Script> script)90 void PendingCompilationErrorHandler::ThrowPendingError(Isolate* isolate,
91 Handle<Script> script) {
92 if (!has_pending_error_) return;
93
94 MessageLocation location = error_details_.GetLocation(script);
95 Handle<String> argument = error_details_.ArgumentString(isolate);
96 isolate->debug()->OnCompileError(script);
97
98 Factory* factory = isolate->factory();
99 Handle<Object> error;
100 switch (error_type_) {
101 case kReferenceError:
102 error = factory->NewReferenceError(error_details_.message(), argument);
103 break;
104 case kSyntaxError:
105 error = factory->NewSyntaxError(error_details_.message(), argument);
106 break;
107 default:
108 UNREACHABLE();
109 break;
110 }
111
112 if (!error->IsJSObject()) {
113 isolate->Throw(*error, &location);
114 return;
115 }
116
117 Handle<JSObject> jserror = Handle<JSObject>::cast(error);
118
119 Handle<Name> key_start_pos = factory->error_start_pos_symbol();
120 JSObject::SetProperty(isolate, jserror, key_start_pos,
121 handle(Smi::FromInt(location.start_pos()), isolate),
122 LanguageMode::kSloppy)
123 .Check();
124
125 Handle<Name> key_end_pos = factory->error_end_pos_symbol();
126 JSObject::SetProperty(isolate, jserror, key_end_pos,
127 handle(Smi::FromInt(location.end_pos()), isolate),
128 LanguageMode::kSloppy)
129 .Check();
130
131 Handle<Name> key_script = factory->error_script_symbol();
132 JSObject::SetProperty(isolate, jserror, key_script, script,
133 LanguageMode::kSloppy)
134 .Check();
135
136 isolate->Throw(*error, &location);
137 }
138
FormatErrorMessageForTest(Isolate * isolate) const139 Handle<String> PendingCompilationErrorHandler::FormatErrorMessageForTest(
140 Isolate* isolate) const {
141 return MessageTemplate::FormatMessage(isolate, error_details_.message(),
142 error_details_.ArgumentString(isolate));
143 }
144
145 } // namespace internal
146 } // namespace v8
147