1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  * vim: set ts=8 sts=4 et sw=4 tw=99:
3  * This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef vm_ErrorObject_h_
8 #define vm_ErrorObject_h_
9 
10 #include "mozilla/ArrayUtils.h"
11 
12 #include "vm/NativeObject.h"
13 #include "vm/SavedStacks.h"
14 #include "vm/Shape.h"
15 
16 namespace js {
17 
18 /*
19  * Initialize the exception constructor/prototype hierarchy.
20  */
21 extern JSObject*
22 InitExceptionClasses(JSContext* cx, HandleObject obj);
23 
24 class ErrorObject : public NativeObject
25 {
26     static JSObject*
27     createProto(JSContext* cx, JSProtoKey key);
28 
29     static JSObject*
30     createConstructor(JSContext* cx, JSProtoKey key);
31 
32     /* For access to createProto. */
33     friend JSObject*
34     js::InitExceptionClasses(JSContext* cx, HandleObject global);
35 
36     static bool
37     init(JSContext* cx, Handle<ErrorObject*> obj, JSExnType type,
38          ScopedJSFreePtr<JSErrorReport>* errorReport, HandleString fileName, HandleObject stack,
39          uint32_t lineNumber, uint32_t columnNumber, HandleString message);
40 
41     static const ClassSpec errorClassSpec_;
42     static const ClassSpec subErrorClassSpec_;
43     static const ClassSpec nonGlobalErrorClassSpec_;
44 
45   protected:
46     static const uint32_t EXNTYPE_SLOT          = 0;
47     static const uint32_t STACK_SLOT            = EXNTYPE_SLOT + 1;
48     static const uint32_t ERROR_REPORT_SLOT     = STACK_SLOT + 1;
49     static const uint32_t FILENAME_SLOT         = ERROR_REPORT_SLOT + 1;
50     static const uint32_t LINENUMBER_SLOT       = FILENAME_SLOT + 1;
51     static const uint32_t COLUMNNUMBER_SLOT     = LINENUMBER_SLOT + 1;
52     static const uint32_t MESSAGE_SLOT          = COLUMNNUMBER_SLOT + 1;
53 
54     static const uint32_t RESERVED_SLOTS = MESSAGE_SLOT + 1;
55 
56   public:
57     static const Class classes[JSEXN_LIMIT];
58 
classForType(JSExnType type)59     static const Class * classForType(JSExnType type) {
60         MOZ_ASSERT(type < JSEXN_WARN);
61         return &classes[type];
62     }
63 
isErrorClass(const Class * clasp)64     static bool isErrorClass(const Class* clasp) {
65         return &classes[0] <= clasp && clasp < &classes[0] + mozilla::ArrayLength(classes);
66     }
67 
68     // Create an error of the given type corresponding to the provided location
69     // info.  If |message| is non-null, then the error will have a .message
70     // property with that value; otherwise the error will have no .message
71     // property.
72     static ErrorObject*
73     create(JSContext* cx, JSExnType type, HandleObject stack, HandleString fileName,
74            uint32_t lineNumber, uint32_t columnNumber, ScopedJSFreePtr<JSErrorReport>* report,
75            HandleString message, HandleObject proto = nullptr);
76 
77     /*
78      * Assign the initial error shape to the empty object.  (This shape does
79      * *not* include .message, which must be added separately if needed; see
80      * ErrorObject::init.)
81      */
82     static Shape*
83     assignInitialShape(ExclusiveContext* cx, Handle<ErrorObject*> obj);
84 
type()85     JSExnType type() const {
86         return JSExnType(getReservedSlot(EXNTYPE_SLOT).toInt32());
87     }
88 
getErrorReport()89     JSErrorReport * getErrorReport() const {
90         const Value& slot = getReservedSlot(ERROR_REPORT_SLOT);
91         if (slot.isUndefined())
92             return nullptr;
93         return static_cast<JSErrorReport*>(slot.toPrivate());
94     }
95 
96     JSErrorReport * getOrCreateErrorReport(JSContext* cx);
97 
98     inline JSString * fileName(JSContext* cx) const;
99     inline uint32_t lineNumber() const;
100     inline uint32_t columnNumber() const;
101     inline JSObject * stack() const;
102 
getMessage()103     JSString * getMessage() const {
104         const HeapSlot& slot = getReservedSlotRef(MESSAGE_SLOT);
105         return slot.isString() ? slot.toString() : nullptr;
106     }
107 
108     // Getter and setter for the Error.prototype.stack accessor.
109     static bool getStack(JSContext* cx, unsigned argc, Value* vp);
110     static bool setStack(JSContext* cx, unsigned argc, Value* vp);
111     static bool setStack_impl(JSContext* cx, const CallArgs& args);
112 };
113 
114 } // namespace js
115 
116 template<>
117 inline bool
118 JSObject::is<js::ErrorObject>() const
119 {
120     return js::ErrorObject::isErrorClass(getClass());
121 }
122 
123 #endif // vm_ErrorObject_h_
124