Merge mozilla-central to autoland. a=merge CLOSED TREE
[gecko.git] / js / public / Exception.h
blob649c40ac472e8e858e3958dacb642e0ecd997362
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
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/. */
7 #ifndef js_Exception_h
8 #define js_Exception_h
10 #include "mozilla/Attributes.h"
11 #include "mozilla/Maybe.h"
13 #include "jstypes.h"
15 #include "js/RootingAPI.h" // JS::{Handle,Rooted}
16 #include "js/TypeDecls.h"
17 #include "js/Value.h" // JS::Value, JS::Handle<JS::Value>
19 class JSErrorReport;
21 namespace JS {
22 enum class ExceptionStackBehavior : bool {
23 // Do not capture any stack.
24 DoNotCapture,
26 // Capture the current JS stack when setting the exception. It may be
27 // retrieved by JS::GetPendingExceptionStack.
28 Capture
30 } // namespace JS
32 extern JS_PUBLIC_API bool JS_IsExceptionPending(JSContext* cx);
34 extern JS_PUBLIC_API bool JS_IsThrowingOutOfMemory(JSContext* cx);
36 extern JS_PUBLIC_API bool JS_GetPendingException(JSContext* cx,
37 JS::MutableHandleValue vp);
39 extern JS_PUBLIC_API void JS_SetPendingException(
40 JSContext* cx, JS::HandleValue v,
41 JS::ExceptionStackBehavior behavior = JS::ExceptionStackBehavior::Capture);
43 extern JS_PUBLIC_API void JS_ClearPendingException(JSContext* cx);
45 /**
46 * If the given object is an exception object, the exception will have (or be
47 * able to lazily create) an error report struct, and this function will return
48 * the address of that struct. Otherwise, it returns nullptr. The lifetime
49 * of the error report struct that might be returned is the same as the
50 * lifetime of the exception object.
52 extern JS_PUBLIC_API JSErrorReport* JS_ErrorFromException(JSContext* cx,
53 JS::HandleObject obj);
55 namespace JS {
57 // When propagating an exception up the call stack, we store the underlying
58 // reason on the JSContext as one of the following enum values.
60 // TODO: Track uncatchable exceptions explicitly.
61 enum class ExceptionStatus {
62 // No exception status.
63 None,
65 // Used by debugger when forcing an early return from a frame. This uses
66 // exception machinery, but at the right time is turned back into a normal
67 // non-error completion.
68 ForcedReturn,
70 // Throwing a (catchable) exception. Certain well-known exceptions are
71 // explicitly tracked for convenience.
72 Throwing,
73 OutOfMemory,
74 OverRecursed,
77 // Returns true if the status is a catchable exception. Formerly this was
78 // indicated by the `JSContext::throwing` flag.
79 static MOZ_ALWAYS_INLINE bool IsCatchableExceptionStatus(
80 ExceptionStatus status) {
81 return status >= ExceptionStatus::Throwing;
84 // This class encapsulates a (pending) exception and the corresponding optional
85 // SavedFrame stack object captured when the pending exception was set
86 // on the JSContext. This fuzzily correlates with a `throw` statement in JS,
87 // although arbitrary JSAPI consumers or VM code may also set pending exceptions
88 // via `JS_SetPendingException`.
90 // This is not the same stack as `e.stack` when `e` is an `Error` object.
91 // (That would be JS::ExceptionStackOrNull).
92 class MOZ_STACK_CLASS ExceptionStack {
93 Rooted<Value> exception_;
94 Rooted<JSObject*> stack_;
96 friend JS_PUBLIC_API bool GetPendingExceptionStack(
97 JSContext* cx, JS::ExceptionStack* exceptionStack);
99 void init(HandleValue exception, HandleObject stack) {
100 exception_ = exception;
101 stack_ = stack;
104 public:
105 explicit ExceptionStack(JSContext* cx) : exception_(cx), stack_(cx) {}
107 ExceptionStack(JSContext* cx, HandleValue exception, HandleObject stack)
108 : exception_(cx, exception), stack_(cx, stack) {}
110 HandleValue exception() const { return exception_; }
112 // |stack| can be null.
113 HandleObject stack() const { return stack_; }
117 * Save and later restore the current exception state of a given JSContext.
118 * This is useful for implementing behavior in C++ that's like try/catch
119 * or try/finally in JS.
121 * Typical usage:
123 * bool ok = JS::Evaluate(cx, ...);
124 * AutoSaveExceptionState savedExc(cx);
125 * ... cleanup that might re-enter JS ...
126 * return ok;
128 class JS_PUBLIC_API AutoSaveExceptionState {
129 private:
130 JSContext* context;
131 ExceptionStatus status;
132 RootedValue exceptionValue;
133 RootedObject exceptionStack;
135 public:
137 * Take a snapshot of cx's current exception state. Then clear any current
138 * pending exception in cx.
140 explicit AutoSaveExceptionState(JSContext* cx);
143 * If neither drop() nor restore() was called, restore the exception
144 * state only if no exception is currently pending on cx.
146 ~AutoSaveExceptionState();
149 * Discard any stored exception state.
150 * If this is called, the destructor is a no-op.
152 void drop();
155 * Replace cx's exception state with the stored exception state. Then
156 * discard the stored exception state. If this is called, the
157 * destructor is a no-op.
159 void restore();
162 // Get the current pending exception value and stack.
163 // This function asserts that there is a pending exception.
164 // If this function returns false, then retrieving the current pending exception
165 // failed and might have been overwritten by a new exception.
166 extern JS_PUBLIC_API bool GetPendingExceptionStack(
167 JSContext* cx, JS::ExceptionStack* exceptionStack);
169 // Similar to GetPendingExceptionStack, but also clears the current
170 // pending exception.
171 extern JS_PUBLIC_API bool StealPendingExceptionStack(
172 JSContext* cx, JS::ExceptionStack* exceptionStack);
174 // Set both the exception value and its associated stack on the context as
175 // the current pending exception.
176 extern JS_PUBLIC_API void SetPendingExceptionStack(
177 JSContext* cx, const JS::ExceptionStack& exceptionStack);
180 * If the given object is an exception object (or an unwrappable
181 * cross-compartment wrapper for one), return the stack for that exception, if
182 * any. Will return null if the given object is not an exception object
183 * (including if it's null or a security wrapper that can't be unwrapped) or if
184 * the exception has no stack.
186 extern JS_PUBLIC_API JSObject* ExceptionStackOrNull(JS::HandleObject obj);
189 * If the given object is an exception object, return the error cause for that
190 * exception, if any, or mozilla::Nothing.
192 extern JS_PUBLIC_API mozilla::Maybe<JS::Value> GetExceptionCause(JSObject* exc);
194 } // namespace JS
196 #endif // js_Exception_h