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 17namespace v8 { 18namespace internal { 19 20void 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 27void 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 34template <typename IsolateT> 35void 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 55Handle<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 75MessageLocation PendingCompilationErrorHandler::MessageDetails::GetLocation( 76 Handle<Script> script) const { 77 return MessageLocation(script, start_position_, end_position_); 78} 79 80void 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 90void 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 100void 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 111void 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 119template <typename IsolateT> 120void PendingCompilationErrorHandler::PrepareWarnings(IsolateT* isolate) { 121 DCHECK(!has_pending_error()); 122 123 for (MessageDetails& warning : warning_messages_) { 124 warning.Prepare(isolate); 125 } 126} 127template void PendingCompilationErrorHandler::PrepareWarnings(Isolate* isolate); 128template void PendingCompilationErrorHandler::PrepareWarnings( 129 LocalIsolate* isolate); 130 131void 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 147template <typename IsolateT> 148void 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} 157template EXPORT_TEMPLATE_DEFINE( 158 V8_EXPORT_PRIVATE) void PendingCompilationErrorHandler:: 159 PrepareErrors(Isolate* isolate, AstValueFactory* ast_value_factory); 160template EXPORT_TEMPLATE_DEFINE( 161 V8_EXPORT_PRIVATE) void PendingCompilationErrorHandler:: 162 PrepareErrors(LocalIsolate* isolate, AstValueFactory* ast_value_factory); 163 164void 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 174void 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 189Handle<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