messages.h 13.1 KB
Newer Older
1
// Copyright 2006-2008 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4 5 6 7 8 9

// The infrastructure used for (localized) message reporting in V8.
//
// Note: there's a big unresolved issue about ownership of the data
// structures used by this framework.

10 11
#ifndef V8_EXECUTION_MESSAGES_H_
#define V8_EXECUTION_MESSAGES_H_
12

13 14
#include <memory>

15
#include "src/base/optional.h"
16
#include "src/common/message-template.h"
17
#include "src/handles/handles.h"
18

19 20
namespace v8 {
namespace internal {
21 22
namespace wasm {
class WasmCode;
23
}  // namespace wasm
24

25
// Forward declarations.
26 27
class AbstractCode;
class FrameArray;
28 29
class JSMessageObject;
class LookupIterator;
30
class PrimitiveHeapObject;
31
class SharedFunctionInfo;
32
class SourceInfo;
33
class WasmInstanceObject;
34

35
class V8_EXPORT_PRIVATE MessageLocation {
36
 public:
37 38 39
  // Constructors for when source positions are already known.
  // TODO(delphick): Collapse to a single constructor with a default parameter
  // 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 44 45 46
  // Constructor for when source positions were not collected but which can be
  // reconstructed from the SharedFuncitonInfo and bytecode offset.
  MessageLocation(Handle<Script> script, Handle<SharedFunctionInfo> shared,
                  int bytecode_offset);
47
  MessageLocation();
48 49 50 51

  Handle<Script> script() const { return script_; }
  int start_pos() const { return start_pos_; }
  int end_pos() const { return end_pos_; }
52
  int bytecode_offset() const { return bytecode_offset_; }
53
  Handle<SharedFunctionInfo> shared() const { return shared_; }
54 55 56 57 58

 private:
  Handle<Script> script_;
  int start_pos_;
  int end_pos_;
59
  int bytecode_offset_;
60
  Handle<SharedFunctionInfo> shared_;
61 62
};

63
class StackFrameBase {
64
 public:
65
  virtual ~StackFrameBase() = default;
66 67 68 69 70

  virtual Handle<Object> GetReceiver() const = 0;
  virtual Handle<Object> GetFunction() const = 0;

  virtual Handle<Object> GetFileName() = 0;
71
  virtual Handle<PrimitiveHeapObject> GetFunctionName() = 0;
72
  virtual Handle<Object> GetScriptNameOrSourceUrl() = 0;
73 74 75 76 77
  virtual Handle<PrimitiveHeapObject> GetMethodName() = 0;
  virtual Handle<PrimitiveHeapObject> GetTypeName() = 0;
  virtual Handle<PrimitiveHeapObject> GetEvalOrigin();
  virtual Handle<PrimitiveHeapObject> GetWasmModuleName();
  virtual Handle<HeapObject> GetWasmInstance();
78

79 80 81
  // Returns the script ID if one is attached, -1 otherwise.
  int GetScriptId() const;

82
  virtual int GetPosition() const = 0;
83
  // Return 1-based line number, including line offset.
84
  virtual int GetLineNumber() = 0;
85
  // Return 1-based column number, including column offset if first line.
86
  virtual int GetColumnNumber() = 0;
87 88
  // Return 0-based Wasm function index. Returns -1 for non-Wasm frames.
  virtual int GetWasmFunctionIndex();
89

90 91 92
  virtual int GetEnclosingColumnNumber() = 0;
  virtual int GetEnclosingLineNumber() = 0;

93 94
  // Returns the index of the rejected promise in the Promise combinator input,
  // or -1 if this frame is not a Promise combinator frame.
95 96
  virtual int GetPromiseIndex() const = 0;

97 98
  virtual bool IsNative() = 0;
  virtual bool IsToplevel() = 0;
99
  virtual bool IsEval();
100
  virtual bool IsAsync() const = 0;
101
  virtual bool IsPromiseAll() const = 0;
102
  virtual bool IsPromiseAny() const = 0;
103 104 105
  virtual bool IsConstructor() = 0;
  virtual bool IsStrict() const = 0;

106 107 108
  // Used to signal that the requested field is unknown.
  static const int kNone = -1;

109
 protected:
110
  StackFrameBase() = default;
111 112 113 114 115 116
  explicit StackFrameBase(Isolate* isolate) : isolate_(isolate) {}
  Isolate* isolate_;

 private:
  virtual bool HasScript() const = 0;
  virtual Handle<Script> GetScript() const = 0;
117 118 119 120 121 122 123
};

class JSStackFrame : public StackFrameBase {
 public:
  JSStackFrame(Isolate* isolate, Handle<Object> receiver,
               Handle<JSFunction> function, Handle<AbstractCode> code,
               int offset);
124
  ~JSStackFrame() override = default;
125 126 127 128 129

  Handle<Object> GetReceiver() const override { return receiver_; }
  Handle<Object> GetFunction() const override;

  Handle<Object> GetFileName() override;
130
  Handle<PrimitiveHeapObject> GetFunctionName() override;
131
  Handle<Object> GetScriptNameOrSourceUrl() override;
132 133
  Handle<PrimitiveHeapObject> GetMethodName() override;
  Handle<PrimitiveHeapObject> GetTypeName() override;
134 135 136 137

  int GetPosition() const override;
  int GetLineNumber() override;
  int GetColumnNumber() override;
138

139 140 141
  int GetEnclosingColumnNumber() override;
  int GetEnclosingLineNumber() override;

142 143
  int GetPromiseIndex() const override;

144 145
  bool IsNative() override;
  bool IsToplevel() override;
146
  bool IsAsync() const override { return is_async_; }
147
  bool IsPromiseAll() const override { return is_promise_all_; }
148
  bool IsPromiseAny() const override { return is_promise_any_; }
149
  bool IsConstructor() override { return is_constructor_; }
150
  bool IsStrict() const override { return is_strict_; }
151 152

 private:
153
  JSStackFrame() = default;
154 155
  void FromFrameArray(Isolate* isolate, Handle<FrameArray> array, int frame_ix);

156 157
  bool HasScript() const override;
  Handle<Script> GetScript() const override;
158

159
  Handle<Object> receiver_;
160 161 162
  Handle<JSFunction> function_;
  Handle<AbstractCode> code_;
  int offset_;
163
  mutable base::Optional<int> cached_position_;
164

165 166
  bool is_async_ : 1;
  bool is_constructor_ : 1;
167
  bool is_promise_all_ : 1;
168
  bool is_promise_any_ : 1;
169
  bool is_strict_ : 1;
170 171 172 173 174 175

  friend class FrameArrayIterator;
};

class WasmStackFrame : public StackFrameBase {
 public:
176
  ~WasmStackFrame() override = default;
177

178
  Handle<Object> GetReceiver() const override;
179 180
  Handle<Object> GetFunction() const override;

181 182
  Handle<Object> GetFileName() override;
  Handle<PrimitiveHeapObject> GetFunctionName() override;
183
  Handle<Object> GetScriptNameOrSourceUrl() override;
184 185 186 187
  Handle<PrimitiveHeapObject> GetMethodName() override { return Null(); }
  Handle<PrimitiveHeapObject> GetTypeName() override { return Null(); }
  Handle<PrimitiveHeapObject> GetWasmModuleName() override;
  Handle<HeapObject> GetWasmInstance() override;
188 189

  int GetPosition() const override;
190
  int GetLineNumber() override { return 0; }
191
  int GetColumnNumber() override;
192 193
  int GetEnclosingColumnNumber() override;
  int GetEnclosingLineNumber() override { return 0; }
194
  int GetWasmFunctionIndex() override { return wasm_func_index_; }
195

196
  int GetPromiseIndex() const override { return GetPosition(); }
197

198 199
  bool IsNative() override { return false; }
  bool IsToplevel() override { return false; }
200
  bool IsAsync() const override { return false; }
201
  bool IsPromiseAll() const override { return false; }
202
  bool IsPromiseAny() const override { return false; }
203 204
  bool IsConstructor() override { return false; }
  bool IsStrict() const override { return false; }
205
  bool IsInterpreted() const { return code_ == nullptr; }
206

207
 protected:
208
  Handle<PrimitiveHeapObject> Null() const;
209

210 211
  bool HasScript() const override;
  Handle<Script> GetScript() const override;
212

213
  Handle<WasmInstanceObject> wasm_instance_;
214
  uint32_t wasm_func_index_;
215
  wasm::WasmCode* code_;  // null for interpreted frames.
216 217
  int offset_;

218
 private:
219 220
  int GetModuleOffset() const;

221
  WasmStackFrame() = default;
222 223
  void FromFrameArray(Isolate* isolate, Handle<FrameArray> array, int frame_ix);

224
  friend class FrameArrayIterator;
225
  friend class AsmJsWasmStackFrame;
226 227
};

228 229
class AsmJsWasmStackFrame : public WasmStackFrame {
 public:
230
  ~AsmJsWasmStackFrame() override = default;
231 232 233 234 235 236 237 238 239 240 241

  Handle<Object> GetReceiver() const override;
  Handle<Object> GetFunction() const override;

  Handle<Object> GetFileName() override;
  Handle<Object> GetScriptNameOrSourceUrl() override;

  int GetPosition() const override;
  int GetLineNumber() override;
  int GetColumnNumber() override;

242 243 244
  int GetEnclosingColumnNumber() override;
  int GetEnclosingLineNumber() override;

245 246
 private:
  friend class FrameArrayIterator;
247
  AsmJsWasmStackFrame() = default;
248 249 250
  void FromFrameArray(Isolate* isolate, Handle<FrameArray> array, int frame_ix);

  bool is_at_number_conversion_;
251 252
};

253 254 255 256 257 258 259
class FrameArrayIterator {
 public:
  FrameArrayIterator(Isolate* isolate, Handle<FrameArray> array,
                     int frame_ix = 0);

  StackFrameBase* Frame();

260 261
  bool HasFrame() const;
  void Advance();
262 263 264 265 266

 private:
  Isolate* isolate_;

  Handle<FrameArray> array_;
267
  int frame_ix_;
268 269

  WasmStackFrame wasm_frame_;
270
  AsmJsWasmStackFrame asm_wasm_frame_;
271
  JSStackFrame js_frame_;
272 273
};

274 275 276 277 278 279 280 281 282 283
// Determines how stack trace collection skips frames.
enum FrameSkipMode {
  // Unconditionally skips the first frame. Used e.g. when the Error constructor
  // is called, in which case the first frame is always a BUILTIN_EXIT frame.
  SKIP_FIRST,
  // Skip all frames until a specified caller function is seen.
  SKIP_UNTIL_SEEN,
  SKIP_NONE,
};

jgruber's avatar
jgruber committed
284 285
class ErrorUtils : public AllStatic {
 public:
286 287 288
  // |kNone| is useful when you don't need the stack information at all, for
  // example when creating a deserialized error.
  enum class StackTraceCollection { kDetailed, kSimple, kNone };
289 290 291 292
  static MaybeHandle<JSObject> Construct(Isolate* isolate,
                                         Handle<JSFunction> target,
                                         Handle<Object> new_target,
                                         Handle<Object> message);
293
  static MaybeHandle<JSObject> Construct(
jgruber's avatar
jgruber committed
294
      Isolate* isolate, Handle<JSFunction> target, Handle<Object> new_target,
295
      Handle<Object> message, FrameSkipMode mode, Handle<Object> caller,
296
      StackTraceCollection stack_trace_collection);
jgruber's avatar
jgruber committed
297 298

  static MaybeHandle<String> ToString(Isolate* isolate, Handle<Object> recv);
299

300
  static Handle<JSObject> MakeGenericError(
301
      Isolate* isolate, Handle<JSFunction> constructor, MessageTemplate index,
302 303
      Handle<Object> arg0, Handle<Object> arg1, Handle<Object> arg2,
      FrameSkipMode mode);
304 305 306 307 308 309

  // Formats a textual stack trace from the given structured stack trace.
  // Note that this can call arbitrary JS code through Error.prepareStackTrace.
  static MaybeHandle<Object> FormatStackTrace(Isolate* isolate,
                                              Handle<JSObject> error,
                                              Handle<Object> stack_trace);
310

311 312 313 314 315 316 317
  static Handle<JSObject> NewIteratorError(Isolate* isolate,
                                           Handle<Object> source);
  static Handle<JSObject> NewCalledNonCallableError(Isolate* isolate,
                                                    Handle<Object> source);
  static Handle<JSObject> NewConstructedNonConstructable(Isolate* isolate,
                                                         Handle<Object> source);
  // Returns the Exception sentinel.
318 319
  static Object ThrowSpreadArgError(Isolate* isolate, MessageTemplate id,
                                    Handle<Object> object);
320
  // Returns the Exception sentinel.
321 322 323
  static Object ThrowLoadFromNullOrUndefined(Isolate* isolate,
                                             Handle<Object> object,
                                             MaybeHandle<Object> key);
jgruber's avatar
jgruber committed
324 325
};

326
class MessageFormatter {
327
 public:
328
  V8_EXPORT_PRIVATE static const char* TemplateString(MessageTemplate index);
329

330 331 332 333 334
  V8_EXPORT_PRIVATE static MaybeHandle<String> Format(Isolate* isolate,
                                                      MessageTemplate index,
                                                      Handle<String> arg0,
                                                      Handle<String> arg1,
                                                      Handle<String> arg2);
335 336

  static Handle<String> Format(Isolate* isolate, MessageTemplate index,
337 338 339
                               Handle<Object> arg0,
                               Handle<Object> arg1 = Handle<Object>(),
                               Handle<Object> arg2 = Handle<Object>());
340 341 342 343 344 345 346
};

// A message handler is a convenience interface for accessing the list
// of message listeners registered in an environment
class MessageHandler {
 public:
  // Returns a message object for the API to use.
347
  V8_EXPORT_PRIVATE static Handle<JSMessageObject> MakeMessageObject(
348 349
      Isolate* isolate, MessageTemplate type, const MessageLocation* location,
      Handle<Object> argument, Handle<FixedArray> stack_frames);
350 351

  // Report a formatted message (needs JS allocation).
352 353 354
  V8_EXPORT_PRIVATE static void ReportMessage(Isolate* isolate,
                                              const MessageLocation* loc,
                                              Handle<JSMessageObject> message);
355 356 357 358

  static void DefaultMessageReport(Isolate* isolate, const MessageLocation* loc,
                                   Handle<Object> message_obj);
  static Handle<String> GetMessage(Isolate* isolate, Handle<Object> data);
359 360
  static std::unique_ptr<char[]> GetLocalizedMessage(Isolate* isolate,
                                                     Handle<Object> data);
361 362 363 364 365 366

 private:
  static void ReportMessageNoExceptions(Isolate* isolate,
                                        const MessageLocation* loc,
                                        Handle<Object> message_obj,
                                        v8::Local<v8::Value> api_exception_obj);
367
};
368

369 370
}  // namespace internal
}  // namespace v8
371

372
#endif  // V8_EXECUTION_MESSAGES_H_