• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "src/base/optional.h"
16 #include "src/common/message-template.h"
17 #include "src/handles/handles.h"
18 
19 namespace v8 {
20 namespace internal {
21 namespace wasm {
22 class WasmCode;
23 }  // namespace wasm
24 
25 // Forward declarations.
26 class AbstractCode;
27 class FrameArray;
28 class JSMessageObject;
29 class LookupIterator;
30 class PrimitiveHeapObject;
31 class SharedFunctionInfo;
32 class SourceInfo;
33 class WasmInstanceObject;
34 
35 class 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 
script()49   Handle<Script> script() const { return script_; }
start_pos()50   int start_pos() const { return start_pos_; }
end_pos()51   int end_pos() const { return end_pos_; }
bytecode_offset()52   int bytecode_offset() const { return bytecode_offset_; }
shared()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 class StackFrameBase {
64  public:
65   virtual ~StackFrameBase() = default;
66 
67   virtual Handle<Object> GetReceiver() const = 0;
68   virtual Handle<Object> GetFunction() const = 0;
69 
70   virtual Handle<Object> GetFileName() = 0;
71   virtual Handle<PrimitiveHeapObject> GetFunctionName() = 0;
72   virtual Handle<Object> GetScriptNameOrSourceUrl() = 0;
73   virtual Handle<PrimitiveHeapObject> GetMethodName() = 0;
74   virtual Handle<PrimitiveHeapObject> GetTypeName() = 0;
75   virtual Handle<PrimitiveHeapObject> GetEvalOrigin();
76   virtual Handle<PrimitiveHeapObject> GetWasmModuleName();
77   virtual Handle<HeapObject> GetWasmInstance();
78 
79   // Returns the script ID if one is attached, -1 otherwise.
80   int GetScriptId() const;
81 
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   // Return 0-based Wasm function index. Returns -1 for non-Wasm frames.
88   virtual int GetWasmFunctionIndex();
89 
90   // Returns the index of the rejected promise in the Promise combinator input,
91   // or -1 if this frame is not a Promise combinator frame.
92   virtual int GetPromiseIndex() const = 0;
93 
94   virtual bool IsNative() = 0;
95   virtual bool IsToplevel() = 0;
96   virtual bool IsEval();
97   virtual bool IsAsync() const = 0;
98   virtual bool IsPromiseAll() const = 0;
99   virtual bool IsPromiseAny() const = 0;
100   virtual bool IsConstructor() = 0;
101   virtual bool IsStrict() const = 0;
102 
103   // Used to signal that the requested field is unknown.
104   static const int kNone = -1;
105 
106  protected:
107   StackFrameBase() = default;
StackFrameBase(Isolate * isolate)108   explicit StackFrameBase(Isolate* isolate) : isolate_(isolate) {}
109   Isolate* isolate_;
110 
111  private:
112   virtual bool HasScript() const = 0;
113   virtual Handle<Script> GetScript() const = 0;
114 };
115 
116 class JSStackFrame : public StackFrameBase {
117  public:
118   JSStackFrame(Isolate* isolate, Handle<Object> receiver,
119                Handle<JSFunction> function, Handle<AbstractCode> code,
120                int offset);
121   ~JSStackFrame() override = default;
122 
GetReceiver()123   Handle<Object> GetReceiver() const override { return receiver_; }
124   Handle<Object> GetFunction() const override;
125 
126   Handle<Object> GetFileName() override;
127   Handle<PrimitiveHeapObject> GetFunctionName() override;
128   Handle<Object> GetScriptNameOrSourceUrl() override;
129   Handle<PrimitiveHeapObject> GetMethodName() override;
130   Handle<PrimitiveHeapObject> GetTypeName() override;
131 
132   int GetPosition() const override;
133   int GetLineNumber() override;
134   int GetColumnNumber() override;
135 
136   int GetPromiseIndex() const override;
137 
138   bool IsNative() override;
139   bool IsToplevel() override;
IsAsync()140   bool IsAsync() const override { return is_async_; }
IsPromiseAll()141   bool IsPromiseAll() const override { return is_promise_all_; }
IsPromiseAny()142   bool IsPromiseAny() const override { return is_promise_any_; }
IsConstructor()143   bool IsConstructor() override { return is_constructor_; }
IsStrict()144   bool IsStrict() const override { return is_strict_; }
145 
146  private:
147   JSStackFrame() = default;
148   void FromFrameArray(Isolate* isolate, Handle<FrameArray> array, int frame_ix);
149 
150   bool HasScript() const override;
151   Handle<Script> GetScript() const override;
152 
153   Handle<Object> receiver_;
154   Handle<JSFunction> function_;
155   Handle<AbstractCode> code_;
156   int offset_;
157   mutable base::Optional<int> cached_position_;
158 
159   bool is_async_ : 1;
160   bool is_constructor_ : 1;
161   bool is_promise_all_ : 1;
162   bool is_promise_any_ : 1;
163   bool is_strict_ : 1;
164 
165   friend class FrameArrayIterator;
166 };
167 
168 class WasmStackFrame : public StackFrameBase {
169  public:
170   ~WasmStackFrame() override = default;
171 
172   Handle<Object> GetReceiver() const override;
173   Handle<Object> GetFunction() const override;
174 
175   Handle<Object> GetFileName() override;
176   Handle<PrimitiveHeapObject> GetFunctionName() override;
177   Handle<Object> GetScriptNameOrSourceUrl() override;
GetMethodName()178   Handle<PrimitiveHeapObject> GetMethodName() override { return Null(); }
GetTypeName()179   Handle<PrimitiveHeapObject> GetTypeName() override { return Null(); }
180   Handle<PrimitiveHeapObject> GetWasmModuleName() override;
181   Handle<HeapObject> GetWasmInstance() override;
182 
183   int GetPosition() const override;
GetLineNumber()184   int GetLineNumber() override { return 0; }
185   int GetColumnNumber() override;
GetWasmFunctionIndex()186   int GetWasmFunctionIndex() override { return wasm_func_index_; }
187 
GetPromiseIndex()188   int GetPromiseIndex() const override { return GetPosition(); }
189 
IsNative()190   bool IsNative() override { return false; }
IsToplevel()191   bool IsToplevel() override { return false; }
IsAsync()192   bool IsAsync() const override { return false; }
IsPromiseAll()193   bool IsPromiseAll() const override { return false; }
IsPromiseAny()194   bool IsPromiseAny() const override { return false; }
IsConstructor()195   bool IsConstructor() override { return false; }
IsStrict()196   bool IsStrict() const override { return false; }
IsInterpreted()197   bool IsInterpreted() const { return code_ == nullptr; }
198 
199  protected:
200   Handle<PrimitiveHeapObject> Null() const;
201 
202   bool HasScript() const override;
203   Handle<Script> GetScript() const override;
204 
205   Handle<WasmInstanceObject> wasm_instance_;
206   uint32_t wasm_func_index_;
207   wasm::WasmCode* code_;  // null for interpreted frames.
208   int offset_;
209 
210  private:
211   int GetModuleOffset() const;
212 
213   WasmStackFrame() = default;
214   void FromFrameArray(Isolate* isolate, Handle<FrameArray> array, int frame_ix);
215 
216   friend class FrameArrayIterator;
217   friend class AsmJsWasmStackFrame;
218 };
219 
220 class AsmJsWasmStackFrame : public WasmStackFrame {
221  public:
222   ~AsmJsWasmStackFrame() override = default;
223 
224   Handle<Object> GetReceiver() const override;
225   Handle<Object> GetFunction() const override;
226 
227   Handle<Object> GetFileName() override;
228   Handle<Object> GetScriptNameOrSourceUrl() override;
229 
230   int GetPosition() const override;
231   int GetLineNumber() override;
232   int GetColumnNumber() override;
233 
234  private:
235   friend class FrameArrayIterator;
236   AsmJsWasmStackFrame() = default;
237   void FromFrameArray(Isolate* isolate, Handle<FrameArray> array, int frame_ix);
238 
239   bool is_at_number_conversion_;
240 };
241 
242 class FrameArrayIterator {
243  public:
244   FrameArrayIterator(Isolate* isolate, Handle<FrameArray> array,
245                      int frame_ix = 0);
246 
247   StackFrameBase* Frame();
248 
249   bool HasFrame() const;
250   void Advance();
251 
252  private:
253   Isolate* isolate_;
254 
255   Handle<FrameArray> array_;
256   int frame_ix_;
257 
258   WasmStackFrame wasm_frame_;
259   AsmJsWasmStackFrame asm_wasm_frame_;
260   JSStackFrame js_frame_;
261 };
262 
263 // Determines how stack trace collection skips frames.
264 enum FrameSkipMode {
265   // Unconditionally skips the first frame. Used e.g. when the Error constructor
266   // is called, in which case the first frame is always a BUILTIN_EXIT frame.
267   SKIP_FIRST,
268   // Skip all frames until a specified caller function is seen.
269   SKIP_UNTIL_SEEN,
270   SKIP_NONE,
271 };
272 
273 class ErrorUtils : public AllStatic {
274  public:
275   // |kNone| is useful when you don't need the stack information at all, for
276   // example when creating a deserialized error.
277   enum class StackTraceCollection { kDetailed, kSimple, kNone };
278   static MaybeHandle<JSObject> Construct(Isolate* isolate,
279                                          Handle<JSFunction> target,
280                                          Handle<Object> new_target,
281                                          Handle<Object> message);
282   static MaybeHandle<JSObject> Construct(
283       Isolate* isolate, Handle<JSFunction> target, Handle<Object> new_target,
284       Handle<Object> message, FrameSkipMode mode, Handle<Object> caller,
285       StackTraceCollection stack_trace_collection);
286 
287   static MaybeHandle<String> ToString(Isolate* isolate, Handle<Object> recv);
288 
289   static Handle<JSObject> MakeGenericError(
290       Isolate* isolate, Handle<JSFunction> constructor, MessageTemplate index,
291       Handle<Object> arg0, Handle<Object> arg1, Handle<Object> arg2,
292       FrameSkipMode mode);
293 
294   // Formats a textual stack trace from the given structured stack trace.
295   // Note that this can call arbitrary JS code through Error.prepareStackTrace.
296   static MaybeHandle<Object> FormatStackTrace(Isolate* isolate,
297                                               Handle<JSObject> error,
298                                               Handle<Object> stack_trace);
299 
300   static Handle<JSObject> NewIteratorError(Isolate* isolate,
301                                            Handle<Object> source);
302   static Handle<JSObject> NewCalledNonCallableError(Isolate* isolate,
303                                                     Handle<Object> source);
304   static Handle<JSObject> NewConstructedNonConstructable(Isolate* isolate,
305                                                          Handle<Object> source);
306   // Returns the Exception sentinel.
307   static Object ThrowSpreadArgError(Isolate* isolate, MessageTemplate id,
308                                     Handle<Object> object);
309   // Returns the Exception sentinel.
310   static Object ThrowLoadFromNullOrUndefined(Isolate* isolate,
311                                              Handle<Object> object,
312                                              MaybeHandle<Object> key);
313 };
314 
315 class MessageFormatter {
316  public:
317   V8_EXPORT_PRIVATE static const char* TemplateString(MessageTemplate index);
318 
319   V8_EXPORT_PRIVATE static MaybeHandle<String> Format(Isolate* isolate,
320                                                       MessageTemplate index,
321                                                       Handle<String> arg0,
322                                                       Handle<String> arg1,
323                                                       Handle<String> arg2);
324 
325   static Handle<String> Format(Isolate* isolate, MessageTemplate index,
326                                Handle<Object> arg0,
327                                Handle<Object> arg1 = Handle<Object>(),
328                                Handle<Object> arg2 = Handle<Object>());
329 };
330 
331 // A message handler is a convenience interface for accessing the list
332 // of message listeners registered in an environment
333 class MessageHandler {
334  public:
335   // Returns a message object for the API to use.
336   V8_EXPORT_PRIVATE static Handle<JSMessageObject> MakeMessageObject(
337       Isolate* isolate, MessageTemplate type, const MessageLocation* location,
338       Handle<Object> argument, Handle<FixedArray> stack_frames);
339 
340   // Report a formatted message (needs JS allocation).
341   V8_EXPORT_PRIVATE static void ReportMessage(Isolate* isolate,
342                                               const MessageLocation* loc,
343                                               Handle<JSMessageObject> message);
344 
345   static void DefaultMessageReport(Isolate* isolate, const MessageLocation* loc,
346                                    Handle<Object> message_obj);
347   static Handle<String> GetMessage(Isolate* isolate, Handle<Object> data);
348   static std::unique_ptr<char[]> GetLocalizedMessage(Isolate* isolate,
349                                                      Handle<Object> data);
350 
351  private:
352   static void ReportMessageNoExceptions(Isolate* isolate,
353                                         const MessageLocation* loc,
354                                         Handle<Object> message_obj,
355                                         v8::Local<v8::Value> api_exception_obj);
356 };
357 
358 }  // namespace internal
359 }  // namespace v8
360 
361 #endif  // V8_EXECUTION_MESSAGES_H_
362