1// Copyright 2006-2008 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// The infrastructure used for (localized) message reporting in V8.
6//
7// Note: there's a big unresolved issue about ownership of the data
8// structures used by this framework.
9
10#ifndef V8_MESSAGES_H_
11#define V8_MESSAGES_H_
12
13#include <memory>
14
15#include "src/handles.h"
16#include "src/message-template.h"
17
18namespace v8 {
19namespace internal {
20namespace wasm {
21class WasmCode;
22}
23
24// Forward declarations.
25class AbstractCode;
26class FrameArray;
27class IncrementalStringBuilder;
28class JSMessageObject;
29class LookupIterator;
30class SharedFunctionInfo;
31class SourceInfo;
32class WasmInstanceObject;
33
34class V8_EXPORT_PRIVATE MessageLocation {
35 public:
36 MessageLocation(Handle<Script> script, int start_pos, int end_pos);
37 MessageLocation(Handle<Script> script, int start_pos, int end_pos,
38 Handle<SharedFunctionInfo> shared);
39 MessageLocation();
40
41 Handle<Script> script() const { return script_; }
42 int start_pos() const { return start_pos_; }
43 int end_pos() const { return end_pos_; }
44 Handle<SharedFunctionInfo> shared() const { return shared_; }
45
46 private:
47 Handle<Script> script_;
48 int start_pos_;
49 int end_pos_;
50 Handle<SharedFunctionInfo> shared_;
51};
52
53class StackFrameBase {
54 public:
55 virtual ~StackFrameBase() = default;
56
57 virtual Handle<Object> GetReceiver() const = 0;
58 virtual Handle<Object> GetFunction() const = 0;
59
60 virtual Handle<Object> GetFileName() = 0;
61 virtual Handle<Object> GetFunctionName() = 0;
62 virtual Handle<Object> GetScriptNameOrSourceUrl() = 0;
63 virtual Handle<Object> GetMethodName() = 0;
64 virtual Handle<Object> GetTypeName() = 0;
65 virtual Handle<Object> GetEvalOrigin();
66
67 // Returns the script ID if one is attached, -1 otherwise.
68 int GetScriptId() const;
69
70 virtual int GetPosition() const = 0;
71 // Return 1-based line number, including line offset.
72 virtual int GetLineNumber() = 0;
73 // Return 1-based column number, including column offset if first line.
74 virtual int GetColumnNumber() = 0;
75
76 // Returns index for Promise.all() async frames, or -1 for other frames.
77 virtual int GetPromiseIndex() const = 0;
78
79 virtual bool IsNative() = 0;
80 virtual bool IsToplevel() = 0;
81 virtual bool IsEval();
82 virtual bool IsAsync() const = 0;
83 virtual bool IsPromiseAll() const = 0;
84 virtual bool IsConstructor() = 0;
85 virtual bool IsStrict() const = 0;
86
87 MaybeHandle<String> ToString();
88 virtual void ToString(IncrementalStringBuilder& builder) = 0;
89
90 // Used to signal that the requested field is unknown.
91 static const int kNone = -1;
92
93 protected:
94 StackFrameBase() = default;
95 explicit StackFrameBase(Isolate* isolate) : isolate_(isolate) {}
96 Isolate* isolate_;
97
98 private:
99 virtual bool HasScript() const = 0;
100 virtual Handle<Script> GetScript() const = 0;
101};
102
103class JSStackFrame : public StackFrameBase {
104 public:
105 JSStackFrame(Isolate* isolate, Handle<Object> receiver,
106 Handle<JSFunction> function, Handle<AbstractCode> code,
107 int offset);
108 ~JSStackFrame() override = default;
109
110 Handle<Object> GetReceiver() const override { return receiver_; }
111 Handle<Object> GetFunction() const override;
112
113 Handle<Object> GetFileName() override;
114 Handle<Object> GetFunctionName() override;
115 Handle<Object> GetScriptNameOrSourceUrl() override;
116 Handle<Object> GetMethodName() override;
117 Handle<Object> GetTypeName() override;
118
119 int GetPosition() const override;
120 int GetLineNumber() override;
121 int GetColumnNumber() override;
122
123 int GetPromiseIndex() const override;
124
125 bool IsNative() override;
126 bool IsToplevel() override;
127 bool IsAsync() const override { return is_async_; }
128 bool IsPromiseAll() const override { return is_promise_all_; }
129 bool IsConstructor() override { return is_constructor_; }
130 bool IsStrict() const override { return is_strict_; }
131
132 void ToString(IncrementalStringBuilder& builder) override;
133
134 private:
135 JSStackFrame() = default;
136 void FromFrameArray(Isolate* isolate, Handle<FrameArray> array, int frame_ix);
137
138 bool HasScript() const override;
139 Handle<Script> GetScript() const override;
140
141 Handle<Object> receiver_;
142 Handle<JSFunction> function_;
143 Handle<AbstractCode> code_;
144 int offset_;
145
146 bool is_async_ : 1;
147 bool is_constructor_ : 1;
148 bool is_promise_all_ : 1;
149 bool is_strict_ : 1;
150
151 friend class FrameArrayIterator;
152};
153
154class WasmStackFrame : public StackFrameBase {
155 public:
156 ~WasmStackFrame() override = default;
157
158 Handle<Object> GetReceiver() const override;
159 Handle<Object> GetFunction() const override;
160
161 Handle<Object> GetFileName() override { return Null(); }
162 Handle<Object> GetFunctionName() override;
163 Handle<Object> GetScriptNameOrSourceUrl() override { return Null(); }
164 Handle<Object> GetMethodName() override { return Null(); }
165 Handle<Object> GetTypeName() override { return Null(); }
166
167 int GetPosition() const override;
168 int GetLineNumber() override { return wasm_func_index_; }
169 int GetColumnNumber() override { return kNone; }
170
171 int GetPromiseIndex() const override { return kNone; }
172
173 bool IsNative() override { return false; }
174 bool IsToplevel() override { return false; }
175 bool IsAsync() const override { return false; }
176 bool IsPromiseAll() const override { return false; }
177 bool IsConstructor() override { return false; }
178 bool IsStrict() const override { return false; }
179 bool IsInterpreted() const { return code_ == nullptr; }
180
181 void ToString(IncrementalStringBuilder& builder) override;
182
183 protected:
184 Handle<Object> Null() const;
185
186 bool HasScript() const override;
187 Handle<Script> GetScript() const override;
188
189 Handle<WasmInstanceObject> wasm_instance_;
190 uint32_t wasm_func_index_;
191 wasm::WasmCode* code_; // null for interpreted frames.
192 int offset_;
193
194 private:
195 WasmStackFrame() = default;
196 void FromFrameArray(Isolate* isolate, Handle<FrameArray> array, int frame_ix);
197
198 friend class FrameArrayIterator;
199 friend class AsmJsWasmStackFrame;
200};
201
202class AsmJsWasmStackFrame : public WasmStackFrame {
203 public:
204 ~AsmJsWasmStackFrame() override = default;
205
206 Handle<Object> GetReceiver() const override;
207 Handle<Object> GetFunction() const override;
208
209 Handle<Object> GetFileName() override;
210 Handle<Object> GetScriptNameOrSourceUrl() override;
211
212 int GetPosition() const override;
213 int GetLineNumber() override;
214 int GetColumnNumber() override;
215
216 void ToString(IncrementalStringBuilder& builder) override;
217
218 private:
219 friend class FrameArrayIterator;
220 AsmJsWasmStackFrame() = default;
221 void FromFrameArray(Isolate* isolate, Handle<FrameArray> array, int frame_ix);
222
223 bool is_at_number_conversion_;
224};
225
226class FrameArrayIterator {
227 public:
228 FrameArrayIterator(Isolate* isolate, Handle<FrameArray> array,
229 int frame_ix = 0);
230
231 StackFrameBase* Frame();
232
233 bool HasFrame() const;
234 void Advance();
235
236 private:
237 Isolate* isolate_;
238
239 Handle<FrameArray> array_;
240 int frame_ix_;
241
242 WasmStackFrame wasm_frame_;
243 AsmJsWasmStackFrame asm_wasm_frame_;
244 JSStackFrame js_frame_;
245};
246
247// Determines how stack trace collection skips frames.
248enum FrameSkipMode {
249 // Unconditionally skips the first frame. Used e.g. when the Error constructor
250 // is called, in which case the first frame is always a BUILTIN_EXIT frame.
251 SKIP_FIRST,
252 // Skip all frames until a specified caller function is seen.
253 SKIP_UNTIL_SEEN,
254 SKIP_NONE,
255};
256
257class ErrorUtils : public AllStatic {
258 public:
259 static MaybeHandle<Object> Construct(
260 Isolate* isolate, Handle<JSFunction> target, Handle<Object> new_target,
261 Handle<Object> message, FrameSkipMode mode, Handle<Object> caller,
262 bool suppress_detailed_trace);
263
264 static MaybeHandle<String> ToString(Isolate* isolate, Handle<Object> recv);
265
266 static MaybeHandle<Object> MakeGenericError(
267 Isolate* isolate, Handle<JSFunction> constructor, MessageTemplate index,
268 Handle<Object> arg0, Handle<Object> arg1, Handle<Object> arg2,
269 FrameSkipMode mode);
270
271 // Formats a textual stack trace from the given structured stack trace.
272 // Note that this can call arbitrary JS code through Error.prepareStackTrace.
273 static MaybeHandle<Object> FormatStackTrace(Isolate* isolate,
274 Handle<JSObject> error,
275 Handle<Object> stack_trace);
276};
277
278class MessageFormatter {
279 public:
280 static const char* TemplateString(MessageTemplate index);
281
282 V8_EXPORT_PRIVATE static MaybeHandle<String> Format(Isolate* isolate,
283 MessageTemplate index,
284 Handle<String> arg0,
285 Handle<String> arg1,
286 Handle<String> arg2);
287
288 static Handle<String> Format(Isolate* isolate, MessageTemplate index,
289 Handle<Object> arg);
290};
291
292
293// A message handler is a convenience interface for accessing the list
294// of message listeners registered in an environment
295class MessageHandler {
296 public:
297 // Returns a message object for the API to use.
298 V8_EXPORT_PRIVATE static Handle<JSMessageObject> MakeMessageObject(
299 Isolate* isolate, MessageTemplate type, const MessageLocation* location,
300 Handle<Object> argument, Handle<FixedArray> stack_frames);
301
302 // Report a formatted message (needs JS allocation).
303 V8_EXPORT_PRIVATE static void ReportMessage(Isolate* isolate,
304 const MessageLocation* loc,
305 Handle<JSMessageObject> message);
306
307 static void DefaultMessageReport(Isolate* isolate, const MessageLocation* loc,
308 Handle<Object> message_obj);
309 static Handle<String> GetMessage(Isolate* isolate, Handle<Object> data);
310 static std::unique_ptr<char[]> GetLocalizedMessage(Isolate* isolate,
311 Handle<Object> data);
312
313 private:
314 static void ReportMessageNoExceptions(Isolate* isolate,
315 const MessageLocation* loc,
316 Handle<Object> message_obj,
317 v8::Local<v8::Value> api_exception_obj);
318};
319
320
321} // namespace internal
322} // namespace v8
323
324#endif // V8_MESSAGES_H_
325