Exception is a JSCell, not a JSObject.
[WebKit-https.git] / Source / JavaScriptCore / runtime / ThrowScope.h
1 /*
2  * Copyright (C) 2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #pragma once
27
28 #include "ExceptionScope.h"
29
30 namespace JSC {
31
32 class ExecState;
33 class JSObject;
34
35 #if ENABLE(EXCEPTION_SCOPE_VERIFICATION)
36
37 // If a function can throw a JS exception, it should declare a ThrowScope at the
38 // top of the function (as early as possible) using the DECLARE_THROW_SCOPE macro.
39 // Declaring a ThrowScope in a function means that the function may throw an
40 // exception that its caller will have to handle.
41
42 class ThrowScope : public ExceptionScope {
43 public:
44     JS_EXPORT_PRIVATE ThrowScope(VM&, ExceptionEventLocation);
45     JS_EXPORT_PRIVATE ~ThrowScope();
46
47     ThrowScope(const ThrowScope&) = delete;
48     ThrowScope(ThrowScope&&) = default;
49
50     JS_EXPORT_PRIVATE Exception* throwException(ExecState*, Exception*);
51     JS_EXPORT_PRIVATE Exception* throwException(ExecState*, JSValue);
52     JS_EXPORT_PRIVATE Exception* throwException(ExecState*, JSObject*);
53
54     void release() { m_isReleased = true; }
55
56     JS_EXPORT_PRIVATE void printIfNeedCheck(const char* functionName, const char* file, unsigned line);
57
58 private:
59     void simulateThrow();
60
61     bool m_isReleased { false };
62 };
63
64 #define DECLARE_THROW_SCOPE(vm__) \
65     JSC::ThrowScope((vm__), JSC::ExceptionEventLocation(EXCEPTION_SCOPE_POSITION_FOR_ASAN, __FUNCTION__, __FILE__, __LINE__))
66
67 #define throwScopePrintIfNeedCheck(scope__) \
68     scope__.printIfNeedCheck(__FUNCTION__, __FILE__, __LINE__)
69
70 #else // not ENABLE(EXCEPTION_SCOPE_VERIFICATION)
71
72 class ThrowScope : public ExceptionScope {
73 public:
74     ALWAYS_INLINE ThrowScope(VM& vm)
75         : ExceptionScope(vm)
76     { }
77     ThrowScope(const ThrowScope&) = delete;
78     ThrowScope(ThrowScope&&) = default;
79
80     ALWAYS_INLINE Exception* throwException(ExecState* exec, Exception* exception) { return m_vm.throwException(exec, exception); }
81     ALWAYS_INLINE Exception* throwException(ExecState* exec, JSValue value) { return m_vm.throwException(exec, value); }
82     ALWAYS_INLINE Exception* throwException(ExecState* exec, JSObject* obj) { return m_vm.throwException(exec, obj); }
83
84     ALWAYS_INLINE void release() { }
85 };
86
87 #define DECLARE_THROW_SCOPE(vm__) \
88     JSC::ThrowScope((vm__))
89
90 #endif // ENABLE(EXCEPTION_SCOPE_VERIFICATION)
91
92 ALWAYS_INLINE Exception* throwException(ExecState* exec, ThrowScope& scope, Exception* exception)
93 {
94     return scope.throwException(exec, exception);
95 }
96
97 ALWAYS_INLINE Exception* throwException(ExecState* exec, ThrowScope& scope, JSValue value)
98 {
99     return scope.throwException(exec, value);
100 }
101
102 ALWAYS_INLINE Exception* throwException(ExecState* exec, ThrowScope& scope, JSObject* obj)
103 {
104     return scope.throwException(exec, obj);
105 }
106
107 } // namespace JSC