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_EXECUTION_MESSAGES_H_
11#define V8_EXECUTION_MESSAGES_H_
12
13#include <memory>
14
15#include "include/v8-local-handle.h"
16#include "src/base/optional.h"
17#include "src/common/message-template.h"
18#include "src/handles/handles.h"
19
20namespace v8 {
21namespace internal {
22namespace wasm {
23class WasmCode;
24}  // namespace wasm
25
26// Forward declarations.
27class AbstractCode;
28class JSMessageObject;
29class LookupIterator;
30class PrimitiveHeapObject;
31class SharedFunctionInfo;
32class SourceInfo;
33class WasmInstanceObject;
34
35class V8_EXPORT_PRIVATE MessageLocation {
36 public:
37  // Constructors for when source positions are already known.
38  // TODO(delphick): Collapse to a single constructor with a default parameter
39  // when we stop using the GCC that requires this separation.
40  MessageLocation(Handle<Script> script, int start_pos, int end_pos);
41  MessageLocation(Handle<Script> script, int start_pos, int end_pos,
42                  Handle<SharedFunctionInfo> shared);
43  // Constructor for when source positions were not collected but which can be
44  // reconstructed from the SharedFuncitonInfo and bytecode offset.
45  MessageLocation(Handle<Script> script, Handle<SharedFunctionInfo> shared,
46                  int bytecode_offset);
47  MessageLocation();
48
49  Handle<Script> script() const { return script_; }
50  int start_pos() const { return start_pos_; }
51  int end_pos() const { return end_pos_; }
52  int bytecode_offset() const { return bytecode_offset_; }
53  Handle<SharedFunctionInfo> shared() const { return shared_; }
54
55 private:
56  Handle<Script> script_;
57  int start_pos_;
58  int end_pos_;
59  int bytecode_offset_;
60  Handle<SharedFunctionInfo> shared_;
61};
62
63// Determines how stack trace collection skips frames.
64enum FrameSkipMode {
65  // Unconditionally skips the first frame. Used e.g. when the Error constructor
66  // is called, in which case the first frame is always a BUILTIN_EXIT frame.
67  SKIP_FIRST,
68  // Skip all frames until a specified caller function is seen.
69  SKIP_UNTIL_SEEN,
70  SKIP_NONE,
71};
72
73class ErrorUtils : public AllStatic {
74 public:
75  // |kDisabled| is useful when you don't need the stack information at all, for
76  // example when creating a deserialized error.
77  enum class StackTraceCollection { kEnabled, kDisabled };
78  static MaybeHandle<JSObject> Construct(Isolate* isolate,
79                                         Handle<JSFunction> target,
80                                         Handle<Object> new_target,
81                                         Handle<Object> message,
82                                         Handle<Object> options);
83  static MaybeHandle<JSObject> Construct(
84      Isolate* isolate, Handle<JSFunction> target, Handle<Object> new_target,
85      Handle<Object> message, Handle<Object> options, FrameSkipMode mode,
86      Handle<Object> caller, StackTraceCollection stack_trace_collection);
87
88  V8_EXPORT_PRIVATE static MaybeHandle<String> ToString(Isolate* isolate,
89                                                        Handle<Object> recv);
90
91  static Handle<JSObject> MakeGenericError(
92      Isolate* isolate, Handle<JSFunction> constructor, MessageTemplate index,
93      Handle<Object> arg0, Handle<Object> arg1, Handle<Object> arg2,
94      FrameSkipMode mode);
95
96  // Formats a textual stack trace from the given structured stack trace.
97  // Note that this can call arbitrary JS code through Error.prepareStackTrace.
98  static MaybeHandle<Object> FormatStackTrace(Isolate* isolate,
99                                              Handle<JSObject> error,
100                                              Handle<Object> stack_trace);
101
102  static Handle<JSObject> NewIteratorError(Isolate* isolate,
103                                           Handle<Object> source);
104  static Handle<JSObject> NewCalledNonCallableError(Isolate* isolate,
105                                                    Handle<Object> source);
106  static Handle<JSObject> NewConstructedNonConstructable(Isolate* isolate,
107                                                         Handle<Object> source);
108  // Returns the Exception sentinel.
109  static Object ThrowSpreadArgError(Isolate* isolate, MessageTemplate id,
110                                    Handle<Object> object);
111  // Returns the Exception sentinel.
112  static Object ThrowLoadFromNullOrUndefined(Isolate* isolate,
113                                             Handle<Object> object,
114                                             MaybeHandle<Object> key);
115
116  static MaybeHandle<Object> GetFormattedStack(Isolate* isolate,
117                                               Handle<JSObject> error_object);
118  static void SetFormattedStack(Isolate* isolate, Handle<JSObject> error_object,
119                                Handle<Object> formatted_stack);
120};
121
122class MessageFormatter {
123 public:
124  V8_EXPORT_PRIVATE static const char* TemplateString(MessageTemplate index);
125
126  V8_EXPORT_PRIVATE static MaybeHandle<String> Format(Isolate* isolate,
127                                                      MessageTemplate index,
128                                                      Handle<String> arg0,
129                                                      Handle<String> arg1,
130                                                      Handle<String> arg2);
131
132  static Handle<String> Format(Isolate* isolate, MessageTemplate index,
133                               Handle<Object> arg0,
134                               Handle<Object> arg1 = Handle<Object>(),
135                               Handle<Object> arg2 = Handle<Object>());
136};
137
138// A message handler is a convenience interface for accessing the list
139// of message listeners registered in an environment
140class MessageHandler {
141 public:
142  // Returns a message object for the API to use.
143  V8_EXPORT_PRIVATE static Handle<JSMessageObject> MakeMessageObject(
144      Isolate* isolate, MessageTemplate type, const MessageLocation* location,
145      Handle<Object> argument, Handle<FixedArray> stack_frames);
146
147  // Report a formatted message (needs JS allocation).
148  V8_EXPORT_PRIVATE static void ReportMessage(Isolate* isolate,
149                                              const MessageLocation* loc,
150                                              Handle<JSMessageObject> message);
151
152  static void DefaultMessageReport(Isolate* isolate, const MessageLocation* loc,
153                                   Handle<Object> message_obj);
154  static Handle<String> GetMessage(Isolate* isolate, Handle<Object> data);
155  static std::unique_ptr<char[]> GetLocalizedMessage(Isolate* isolate,
156                                                     Handle<Object> data);
157
158 private:
159  static void ReportMessageNoExceptions(Isolate* isolate,
160                                        const MessageLocation* loc,
161                                        Handle<Object> message_obj,
162                                        v8::Local<v8::Value> api_exception_obj);
163};
164
165}  // namespace internal
166}  // namespace v8
167
168#endif  // V8_EXECUTION_MESSAGES_H_
169