// Copyright 2015 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "src/pending-compilation-error-handler.h" #include "src/ast/ast-value-factory.h" #include "src/debug/debug.h" #include "src/handles.h" #include "src/isolate.h" #include "src/messages.h" #include "src/objects-inl.h" namespace v8 { namespace internal { Handle<String> PendingCompilationErrorHandler::MessageDetails::ArgumentString( Isolate* isolate) const { if (arg_ != nullptr) return arg_->string(); if (char_arg_ != nullptr) { return isolate->factory() ->NewStringFromUtf8(CStrVector(char_arg_)) .ToHandleChecked(); } return isolate->factory()->undefined_string(); } MessageLocation PendingCompilationErrorHandler::MessageDetails::GetLocation( Handle<Script> script) const { return MessageLocation(script, start_position_, end_position_); } void PendingCompilationErrorHandler::ReportMessageAt( int start_position, int end_position, MessageTemplate message, const char* arg, ParseErrorType error_type) { if (has_pending_error_) return; has_pending_error_ = true; error_details_ = MessageDetails(start_position, end_position, message, nullptr, arg); error_type_ = error_type; } void PendingCompilationErrorHandler::ReportMessageAt( int start_position, int end_position, MessageTemplate message, const AstRawString* arg, ParseErrorType error_type) { if (has_pending_error_) return; has_pending_error_ = true; error_details_ = MessageDetails(start_position, end_position, message, arg, nullptr); error_type_ = error_type; } void PendingCompilationErrorHandler::ReportWarningAt(int start_position, int end_position, MessageTemplate message, const char* arg) { warning_messages_.emplace_front( MessageDetails(start_position, end_position, message, nullptr, arg)); } void PendingCompilationErrorHandler::ReportWarnings(Isolate* isolate, Handle<Script> script) { DCHECK(!has_pending_error()); for (const MessageDetails& warning : warning_messages_) { MessageLocation location = warning.GetLocation(script); Handle<String> argument = warning.ArgumentString(isolate); Handle<JSMessageObject> message = MessageHandler::MakeMessageObject(isolate, warning.message(), &location, argument, Handle<FixedArray>::null()); message->set_error_level(v8::Isolate::kMessageWarning); MessageHandler::ReportMessage(isolate, &location, message); } } void PendingCompilationErrorHandler::ReportErrors( Isolate* isolate, Handle<Script> script, AstValueFactory* ast_value_factory) { if (stack_overflow()) { isolate->StackOverflow(); } else { DCHECK(has_pending_error()); // Internalize ast values for throwing the pending error. ast_value_factory->Internalize(isolate); ThrowPendingError(isolate, script); } } void PendingCompilationErrorHandler::ThrowPendingError(Isolate* isolate, Handle<Script> script) { if (!has_pending_error_) return; MessageLocation location = error_details_.GetLocation(script); Handle<String> argument = error_details_.ArgumentString(isolate); isolate->debug()->OnCompileError(script); Factory* factory = isolate->factory(); Handle<Object> error; switch (error_type_) { case kReferenceError: error = factory->NewReferenceError(error_details_.message(), argument); break; case kSyntaxError: error = factory->NewSyntaxError(error_details_.message(), argument); break; default: UNREACHABLE(); break; } if (!error->IsJSObject()) { isolate->Throw(*error, &location); return; } Handle<JSObject> jserror = Handle<JSObject>::cast(error); Handle<Name> key_start_pos = factory->error_start_pos_symbol(); Object::SetProperty(isolate, jserror, key_start_pos, handle(Smi::FromInt(location.start_pos()), isolate), StoreOrigin::kMaybeKeyed, Just(ShouldThrow::kThrowOnError)) .Check(); Handle<Name> key_end_pos = factory->error_end_pos_symbol(); Object::SetProperty(isolate, jserror, key_end_pos, handle(Smi::FromInt(location.end_pos()), isolate), StoreOrigin::kMaybeKeyed, Just(ShouldThrow::kThrowOnError)) .Check(); Handle<Name> key_script = factory->error_script_symbol(); Object::SetProperty(isolate, jserror, key_script, script, StoreOrigin::kMaybeKeyed, Just(ShouldThrow::kThrowOnError)) .Check(); isolate->Throw(*error, &location); } Handle<String> PendingCompilationErrorHandler::FormatErrorMessageForTest( Isolate* isolate) const { return MessageFormatter::FormatMessage( isolate, error_details_.message(), error_details_.ArgumentString(isolate)); } } // namespace internal } // namespace v8