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
14namespace v8 {
15namespace internal {
16
17Handle<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
28MessageLocation PendingCompilationErrorHandler::MessageDetails::GetLocation(
29 Handle<Script> script) const {
30 return MessageLocation(script, start_position_, end_position_);
31}
32
33void PendingCompilationErrorHandler::ReportMessageAt(
34 int start_position, int end_position, MessageTemplate 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
44void PendingCompilationErrorHandler::ReportMessageAt(
45 int start_position, int end_position, MessageTemplate 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
55void PendingCompilationErrorHandler::ReportWarningAt(int start_position,
56 int end_position,
57 MessageTemplate message,
58 const char* arg) {
59 warning_messages_.emplace_front(
60 MessageDetails(start_position, end_position, message, nullptr, arg));
61}
62
63void PendingCompilationErrorHandler::ReportWarnings(Isolate* isolate,
64 Handle<Script> script) {
65 DCHECK(!has_pending_error());
66
67 for (const MessageDetails& warning : warning_messages_) {
68 MessageLocation location = warning.GetLocation(script);
69 Handle<String> argument = warning.ArgumentString(isolate);
70 Handle<JSMessageObject> message =
71 MessageHandler::MakeMessageObject(isolate, warning.message(), &location,
72 argument, Handle<FixedArray>::null());
73 message->set_error_level(v8::Isolate::kMessageWarning);
74 MessageHandler::ReportMessage(isolate, &location, message);
75 }
76}
77
78void PendingCompilationErrorHandler::ReportErrors(
79 Isolate* isolate, Handle<Script> script,
80 AstValueFactory* ast_value_factory) {
81 if (stack_overflow()) {
82 isolate->StackOverflow();
83 } else {
84 DCHECK(has_pending_error());
85 // Internalize ast values for throwing the pending error.
86 ast_value_factory->Internalize(isolate);
87 ThrowPendingError(isolate, script);
88 }
89}
90
91void PendingCompilationErrorHandler::ThrowPendingError(Isolate* isolate,
92 Handle<Script> script) {
93 if (!has_pending_error_) return;
94
95 MessageLocation location = error_details_.GetLocation(script);
96 Handle<String> argument = error_details_.ArgumentString(isolate);
97 isolate->debug()->OnCompileError(script);
98
99 Factory* factory = isolate->factory();
100 Handle<Object> error;
101 switch (error_type_) {
102 case kReferenceError:
103 error = factory->NewReferenceError(error_details_.message(), argument);
104 break;
105 case kSyntaxError:
106 error = factory->NewSyntaxError(error_details_.message(), argument);
107 break;
108 default:
109 UNREACHABLE();
110 break;
111 }
112
113 if (!error->IsJSObject()) {
114 isolate->Throw(*error, &location);
115 return;
116 }
117
118 Handle<JSObject> jserror = Handle<JSObject>::cast(error);
119
120 Handle<Name> key_start_pos = factory->error_start_pos_symbol();
121 Object::SetProperty(isolate, jserror, key_start_pos,
122 handle(Smi::FromInt(location.start_pos()), isolate),
123 StoreOrigin::kMaybeKeyed,
124 Just(ShouldThrow::kThrowOnError))
125 .Check();
126
127 Handle<Name> key_end_pos = factory->error_end_pos_symbol();
128 Object::SetProperty(isolate, jserror, key_end_pos,
129 handle(Smi::FromInt(location.end_pos()), isolate),
130 StoreOrigin::kMaybeKeyed,
131 Just(ShouldThrow::kThrowOnError))
132 .Check();
133
134 Handle<Name> key_script = factory->error_script_symbol();
135 Object::SetProperty(isolate, jserror, key_script, script,
136 StoreOrigin::kMaybeKeyed,
137 Just(ShouldThrow::kThrowOnError))
138 .Check();
139
140 isolate->Throw(*error, &location);
141}
142
143Handle<String> PendingCompilationErrorHandler::FormatErrorMessageForTest(
144 Isolate* isolate) const {
145 return MessageFormatter::Format(isolate, error_details_.message(),
146 error_details_.ArgumentString(isolate));
147}
148
149} // namespace internal
150} // namespace v8
151