• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/parsing/pending-compilation-error-handler.h"
6 
7 #include "src/ast/ast-value-factory.h"
8 #include "src/base/export-template.h"
9 #include "src/base/logging.h"
10 #include "src/debug/debug.h"
11 #include "src/execution/isolate.h"
12 #include "src/execution/messages.h"
13 #include "src/handles/handles.h"
14 #include "src/heap/local-heap-inl.h"
15 #include "src/objects/objects-inl.h"
16 
17 namespace v8 {
18 namespace internal {
19 
SetString(Handle<String> string,Isolate * isolate)20 void PendingCompilationErrorHandler::MessageDetails::SetString(
21     Handle<String> string, Isolate* isolate) {
22   DCHECK_NE(args_[0].type, kMainThreadHandle);
23   args_[0].type = kMainThreadHandle;
24   args_[0].js_string = string;
25 }
26 
SetString(Handle<String> string,LocalIsolate * isolate)27 void PendingCompilationErrorHandler::MessageDetails::SetString(
28     Handle<String> string, LocalIsolate* isolate) {
29   DCHECK_NE(args_[0].type, kMainThreadHandle);
30   args_[0].type = kMainThreadHandle;
31   args_[0].js_string = isolate->heap()->NewPersistentHandle(string);
32 }
33 
34 template <typename IsolateT>
Prepare(IsolateT * isolate)35 void PendingCompilationErrorHandler::MessageDetails::Prepare(
36     IsolateT* isolate) {
37   for (int i = 0; i < kMaxArgumentCount; i++) {
38     switch (args_[i].type) {
39       case kAstRawString:
40         return SetString(args_[i].ast_string->string(), isolate);
41 
42       case kNone:
43       case kConstCharString:
44         // We can delay allocation until ArgString(isolate).
45         return;
46 
47       case kMainThreadHandle:
48         // The message details might already be prepared, so skip them if this
49         // is the case.
50         return;
51     }
52   }
53 }
54 
ArgString(Isolate * isolate,int index) const55 Handle<String> PendingCompilationErrorHandler::MessageDetails::ArgString(
56     Isolate* isolate, int index) const {
57   // `index` may be >= argc; in that case we return a default value to pass on
58   // elsewhere.
59   DCHECK_LT(index, kMaxArgumentCount);
60   switch (args_[index].type) {
61     case kMainThreadHandle:
62       return args_[index].js_string;
63     case kNone:
64       return Handle<String>::null();
65     case kConstCharString:
66       return isolate->factory()
67           ->NewStringFromUtf8(base::CStrVector(args_[index].c_string),
68                               AllocationType::kOld)
69           .ToHandleChecked();
70     case kAstRawString:
71       UNREACHABLE();
72   }
73 }
74 
GetLocation(Handle<Script> script) const75 MessageLocation PendingCompilationErrorHandler::MessageDetails::GetLocation(
76     Handle<Script> script) const {
77   return MessageLocation(script, start_position_, end_position_);
78 }
79 
ReportMessageAt(int start_position,int end_position,MessageTemplate message,const char * arg)80 void PendingCompilationErrorHandler::ReportMessageAt(int start_position,
81                                                      int end_position,
82                                                      MessageTemplate message,
83                                                      const char* arg) {
84   if (has_pending_error_) return;
85   has_pending_error_ = true;
86 
87   error_details_ = MessageDetails(start_position, end_position, message, arg);
88 }
89 
ReportMessageAt(int start_position,int end_position,MessageTemplate message,const AstRawString * arg)90 void PendingCompilationErrorHandler::ReportMessageAt(int start_position,
91                                                      int end_position,
92                                                      MessageTemplate message,
93                                                      const AstRawString* arg) {
94   if (has_pending_error_) return;
95   has_pending_error_ = true;
96 
97   error_details_ = MessageDetails(start_position, end_position, message, arg);
98 }
99 
ReportMessageAt(int start_position,int end_position,MessageTemplate message,const AstRawString * arg0,const char * arg1)100 void PendingCompilationErrorHandler::ReportMessageAt(int start_position,
101                                                      int end_position,
102                                                      MessageTemplate message,
103                                                      const AstRawString* arg0,
104                                                      const char* arg1) {
105   if (has_pending_error_) return;
106   has_pending_error_ = true;
107   error_details_ =
108       MessageDetails(start_position, end_position, message, arg0, arg1);
109 }
110 
ReportWarningAt(int start_position,int end_position,MessageTemplate message,const char * arg)111 void PendingCompilationErrorHandler::ReportWarningAt(int start_position,
112                                                      int end_position,
113                                                      MessageTemplate message,
114                                                      const char* arg) {
115   warning_messages_.emplace_front(
116       MessageDetails(start_position, end_position, message, arg));
117 }
118 
119 template <typename IsolateT>
PrepareWarnings(IsolateT * isolate)120 void PendingCompilationErrorHandler::PrepareWarnings(IsolateT* isolate) {
121   DCHECK(!has_pending_error());
122 
123   for (MessageDetails& warning : warning_messages_) {
124     warning.Prepare(isolate);
125   }
126 }
127 template void PendingCompilationErrorHandler::PrepareWarnings(Isolate* isolate);
128 template void PendingCompilationErrorHandler::PrepareWarnings(
129     LocalIsolate* isolate);
130 
ReportWarnings(Isolate * isolate,Handle<Script> script) const131 void PendingCompilationErrorHandler::ReportWarnings(
132     Isolate* isolate, Handle<Script> script) const {
133   DCHECK(!has_pending_error());
134 
135   for (const MessageDetails& warning : warning_messages_) {
136     MessageLocation location = warning.GetLocation(script);
137     Handle<String> argument = warning.ArgString(isolate, 0);
138     DCHECK_LT(warning.ArgCount(), 2);  // Arg1 is only used for errors.
139     Handle<JSMessageObject> message =
140         MessageHandler::MakeMessageObject(isolate, warning.message(), &location,
141                                           argument, Handle<FixedArray>::null());
142     message->set_error_level(v8::Isolate::kMessageWarning);
143     MessageHandler::ReportMessage(isolate, &location, message);
144   }
145 }
146 
147 template <typename IsolateT>
PrepareErrors(IsolateT * isolate,AstValueFactory * ast_value_factory)148 void PendingCompilationErrorHandler::PrepareErrors(
149     IsolateT* isolate, AstValueFactory* ast_value_factory) {
150   if (stack_overflow()) return;
151 
152   DCHECK(has_pending_error());
153   // Internalize ast values for throwing the pending error.
154   ast_value_factory->Internalize(isolate);
155   error_details_.Prepare(isolate);
156 }
157 template EXPORT_TEMPLATE_DEFINE(
158     V8_EXPORT_PRIVATE) void PendingCompilationErrorHandler::
159     PrepareErrors(Isolate* isolate, AstValueFactory* ast_value_factory);
160 template EXPORT_TEMPLATE_DEFINE(
161     V8_EXPORT_PRIVATE) void PendingCompilationErrorHandler::
162     PrepareErrors(LocalIsolate* isolate, AstValueFactory* ast_value_factory);
163 
ReportErrors(Isolate * isolate,Handle<Script> script) const164 void PendingCompilationErrorHandler::ReportErrors(Isolate* isolate,
165                                                   Handle<Script> script) const {
166   if (stack_overflow()) {
167     isolate->StackOverflow();
168   } else {
169     DCHECK(has_pending_error());
170     ThrowPendingError(isolate, script);
171   }
172 }
173 
ThrowPendingError(Isolate * isolate,Handle<Script> script) const174 void PendingCompilationErrorHandler::ThrowPendingError(
175     Isolate* isolate, Handle<Script> script) const {
176   if (!has_pending_error_) return;
177 
178   MessageLocation location = error_details_.GetLocation(script);
179   Handle<String> arg0 = error_details_.ArgString(isolate, 0);
180   Handle<String> arg1 = error_details_.ArgString(isolate, 1);
181   isolate->debug()->OnCompileError(script);
182 
183   Factory* factory = isolate->factory();
184   Handle<JSObject> error =
185       factory->NewSyntaxError(error_details_.message(), arg0, arg1);
186   isolate->ThrowAt(error, &location);
187 }
188 
FormatErrorMessageForTest(Isolate * isolate)189 Handle<String> PendingCompilationErrorHandler::FormatErrorMessageForTest(
190     Isolate* isolate) {
191   error_details_.Prepare(isolate);
192   return MessageFormatter::Format(isolate, error_details_.message(),
193                                   error_details_.ArgString(isolate, 0),
194                                   error_details_.ArgString(isolate, 1));
195 }
196 
197 }  // namespace internal
198 }  // namespace v8
199