• 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(type_, kMainThreadHandle);
23   type_ = kMainThreadHandle;
24   arg_handle_ = string;
25 }
26 
SetString(Handle<String> string,LocalIsolate * isolate)27 void PendingCompilationErrorHandler::MessageDetails::SetString(
28     Handle<String> string, LocalIsolate* isolate) {
29   DCHECK_NE(type_, kMainThreadHandle);
30   type_ = kMainThreadHandle;
31   arg_handle_ = isolate->heap()->NewPersistentHandle(string);
32 }
33 
34 template <typename LocalIsolate>
Prepare(LocalIsolate * isolate)35 void PendingCompilationErrorHandler::MessageDetails::Prepare(
36     LocalIsolate* isolate) {
37   switch (type_) {
38     case kAstRawString:
39       return SetString(arg_->string(), isolate);
40 
41     case kNone:
42     case kConstCharString:
43       // We can delay allocation until ArgumentString(isolate).
44       // TODO(leszeks): We don't actually have to transfer this string, since
45       // it's a root.
46       return;
47 
48     case kMainThreadHandle:
49       // The message details might already be prepared, so skip them if this is
50       // the case.
51       return;
52   }
53 }
54 
ArgumentString(Isolate * isolate) const55 Handle<String> PendingCompilationErrorHandler::MessageDetails::ArgumentString(
56     Isolate* isolate) const {
57   switch (type_) {
58     case kMainThreadHandle:
59       return arg_handle_;
60     case kNone:
61       return isolate->factory()->undefined_string();
62     case kConstCharString:
63       return isolate->factory()
64           ->NewStringFromUtf8(CStrVector(char_arg_), AllocationType::kOld)
65           .ToHandleChecked();
66     case kAstRawString:
67       UNREACHABLE();
68   }
69 }
70 
GetLocation(Handle<Script> script) const71 MessageLocation PendingCompilationErrorHandler::MessageDetails::GetLocation(
72     Handle<Script> script) const {
73   return MessageLocation(script, start_position_, end_position_);
74 }
75 
ReportMessageAt(int start_position,int end_position,MessageTemplate message,const char * arg)76 void PendingCompilationErrorHandler::ReportMessageAt(int start_position,
77                                                      int end_position,
78                                                      MessageTemplate message,
79                                                      const char* arg) {
80   if (has_pending_error_) return;
81   has_pending_error_ = true;
82 
83   error_details_ = MessageDetails(start_position, end_position, message, arg);
84 }
85 
ReportMessageAt(int start_position,int end_position,MessageTemplate message,const AstRawString * arg)86 void PendingCompilationErrorHandler::ReportMessageAt(int start_position,
87                                                      int end_position,
88                                                      MessageTemplate message,
89                                                      const AstRawString* arg) {
90   if (has_pending_error_) return;
91   has_pending_error_ = true;
92 
93   error_details_ = MessageDetails(start_position, end_position, message, arg);
94 }
95 
ReportWarningAt(int start_position,int end_position,MessageTemplate message,const char * arg)96 void PendingCompilationErrorHandler::ReportWarningAt(int start_position,
97                                                      int end_position,
98                                                      MessageTemplate message,
99                                                      const char* arg) {
100   warning_messages_.emplace_front(
101       MessageDetails(start_position, end_position, message, arg));
102 }
103 
104 template <typename LocalIsolate>
PrepareWarnings(LocalIsolate * isolate)105 void PendingCompilationErrorHandler::PrepareWarnings(LocalIsolate* isolate) {
106   DCHECK(!has_pending_error());
107 
108   for (MessageDetails& warning : warning_messages_) {
109     warning.Prepare(isolate);
110   }
111 }
112 template void PendingCompilationErrorHandler::PrepareWarnings(Isolate* isolate);
113 template void PendingCompilationErrorHandler::PrepareWarnings(
114     LocalIsolate* isolate);
115 
ReportWarnings(Isolate * isolate,Handle<Script> script) const116 void PendingCompilationErrorHandler::ReportWarnings(
117     Isolate* isolate, Handle<Script> script) const {
118   DCHECK(!has_pending_error());
119 
120   for (const MessageDetails& warning : warning_messages_) {
121     MessageLocation location = warning.GetLocation(script);
122     Handle<String> argument = warning.ArgumentString(isolate);
123     Handle<JSMessageObject> message =
124         MessageHandler::MakeMessageObject(isolate, warning.message(), &location,
125                                           argument, Handle<FixedArray>::null());
126     message->set_error_level(v8::Isolate::kMessageWarning);
127     MessageHandler::ReportMessage(isolate, &location, message);
128   }
129 }
130 
131 template <typename LocalIsolate>
PrepareErrors(LocalIsolate * isolate,AstValueFactory * ast_value_factory)132 void PendingCompilationErrorHandler::PrepareErrors(
133     LocalIsolate* isolate, AstValueFactory* ast_value_factory) {
134   if (stack_overflow()) return;
135 
136   DCHECK(has_pending_error());
137   // Internalize ast values for throwing the pending error.
138   ast_value_factory->Internalize(isolate);
139   error_details_.Prepare(isolate);
140 }
141 template EXPORT_TEMPLATE_DEFINE(
142     V8_EXPORT_PRIVATE) void PendingCompilationErrorHandler::
143     PrepareErrors(Isolate* isolate, AstValueFactory* ast_value_factory);
144 template EXPORT_TEMPLATE_DEFINE(
145     V8_EXPORT_PRIVATE) void PendingCompilationErrorHandler::
146     PrepareErrors(LocalIsolate* isolate, AstValueFactory* ast_value_factory);
147 
ReportErrors(Isolate * isolate,Handle<Script> script) const148 void PendingCompilationErrorHandler::ReportErrors(Isolate* isolate,
149                                                   Handle<Script> script) const {
150   if (stack_overflow()) {
151     isolate->StackOverflow();
152   } else {
153     DCHECK(has_pending_error());
154     ThrowPendingError(isolate, script);
155   }
156 }
157 
ThrowPendingError(Isolate * isolate,Handle<Script> script) const158 void PendingCompilationErrorHandler::ThrowPendingError(
159     Isolate* isolate, Handle<Script> script) const {
160   if (!has_pending_error_) return;
161 
162   MessageLocation location = error_details_.GetLocation(script);
163   Handle<String> argument = error_details_.ArgumentString(isolate);
164   isolate->debug()->OnCompileError(script);
165 
166   Factory* factory = isolate->factory();
167   Handle<JSObject> error =
168       factory->NewSyntaxError(error_details_.message(), argument);
169   isolate->ThrowAt(error, &location);
170 }
171 
FormatErrorMessageForTest(Isolate * isolate)172 Handle<String> PendingCompilationErrorHandler::FormatErrorMessageForTest(
173     Isolate* isolate) {
174   error_details_.Prepare(isolate);
175   return MessageFormatter::Format(isolate, error_details_.message(),
176                                   error_details_.ArgumentString(isolate));
177 }
178 
179 }  // namespace internal
180 }  // namespace v8
181