1 | /* |
2 | * Copyright (C) 2005-2018 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 | * |
8 | * 1. Redistributions of source code must retain the above copyright |
9 | * notice, this list of conditions and the following disclaimer. |
10 | * 2. Redistributions in binary form must reproduce the above copyright |
11 | * notice, this list of conditions and the following disclaimer in the |
12 | * documentation and/or other materials provided with the distribution. |
13 | * 3. Neither the name of Apple Inc. ("Apple") nor the names of |
14 | * its contributors may be used to endorse or promote products derived |
15 | * from this software without specific prior written permission. |
16 | * |
17 | * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
18 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
20 | * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
21 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
22 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
23 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
24 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | */ |
28 | |
29 | #pragma once |
30 | |
31 | #include <JavaScriptCore/JSContextRef.h> |
32 | #include <JavaScriptCore/JSStringRef.h> |
33 | #include <algorithm> |
34 | |
35 | inline void JSRetain(JSStringRef string) { JSStringRetain(string); } |
36 | inline void JSRelease(JSStringRef string) { JSStringRelease(string); } |
37 | inline void JSRetain(JSGlobalContextRef context) { JSGlobalContextRetain(context); } |
38 | inline void JSRelease(JSGlobalContextRef context) { JSGlobalContextRelease(context); } |
39 | |
40 | enum AdoptTag { Adopt }; |
41 | |
42 | template<typename T> class JSRetainPtr { |
43 | public: |
44 | JSRetainPtr() = default; |
45 | JSRetainPtr(T ptr) : m_ptr(ptr) { if (ptr) JSRetain(ptr); } |
46 | JSRetainPtr(const JSRetainPtr&); |
47 | JSRetainPtr(JSRetainPtr&&); |
48 | ~JSRetainPtr(); |
49 | |
50 | T get() const { return m_ptr; } |
51 | |
52 | void clear(); |
53 | T leakRef() WARN_UNUSED_RETURN; |
54 | |
55 | T operator->() const { return m_ptr; } |
56 | |
57 | bool operator!() const { return !m_ptr; } |
58 | explicit operator bool() const { return m_ptr; } |
59 | |
60 | JSRetainPtr& operator=(const JSRetainPtr&); |
61 | JSRetainPtr& operator=(JSRetainPtr&&); |
62 | JSRetainPtr& operator=(T); |
63 | |
64 | void swap(JSRetainPtr&); |
65 | |
66 | friend JSRetainPtr<JSStringRef> adopt(JSStringRef); |
67 | friend JSRetainPtr<JSGlobalContextRef> adopt(JSGlobalContextRef); |
68 | |
69 | // FIXME: Make this private once Apple's internal code is updated to not rely on it. |
70 | // https://bugs.webkit.org/show_bug.cgi?id=189644 |
71 | JSRetainPtr(AdoptTag, T); |
72 | |
73 | private: |
74 | T m_ptr { nullptr }; |
75 | }; |
76 | |
77 | JSRetainPtr<JSStringRef> adopt(JSStringRef); |
78 | JSRetainPtr<JSGlobalContextRef> adopt(JSGlobalContextRef); |
79 | |
80 | template<typename T> inline JSRetainPtr<T>::JSRetainPtr(AdoptTag, T ptr) |
81 | : m_ptr(ptr) |
82 | { |
83 | } |
84 | |
85 | inline JSRetainPtr<JSStringRef> adopt(JSStringRef o) |
86 | { |
87 | return JSRetainPtr<JSStringRef>(Adopt, o); |
88 | } |
89 | |
90 | inline JSRetainPtr<JSGlobalContextRef> adopt(JSGlobalContextRef o) |
91 | { |
92 | return JSRetainPtr<JSGlobalContextRef>(Adopt, o); |
93 | } |
94 | |
95 | template<typename T> inline JSRetainPtr<T>::JSRetainPtr(const JSRetainPtr& o) |
96 | : m_ptr(o.m_ptr) |
97 | { |
98 | if (m_ptr) |
99 | JSRetain(m_ptr); |
100 | } |
101 | |
102 | template<typename T> inline JSRetainPtr<T>::JSRetainPtr(JSRetainPtr&& o) |
103 | : m_ptr(o.leakRef()) |
104 | { |
105 | } |
106 | |
107 | template<typename T> inline JSRetainPtr<T>::~JSRetainPtr() |
108 | { |
109 | if (m_ptr) |
110 | JSRelease(m_ptr); |
111 | } |
112 | |
113 | template<typename T> inline void JSRetainPtr<T>::clear() |
114 | { |
115 | if (T ptr = leakRef()) |
116 | JSRelease(ptr); |
117 | } |
118 | |
119 | template<typename T> inline T JSRetainPtr<T>::leakRef() |
120 | { |
121 | return std::exchange(m_ptr, nullptr); |
122 | } |
123 | |
124 | template<typename T> inline JSRetainPtr<T>& JSRetainPtr<T>::operator=(const JSRetainPtr<T>& o) |
125 | { |
126 | return operator=(o.get()); |
127 | } |
128 | |
129 | template<typename T> inline JSRetainPtr<T>& JSRetainPtr<T>::operator=(JSRetainPtr&& o) |
130 | { |
131 | if (T ptr = std::exchange(m_ptr, o.leakRef())) |
132 | JSRelease(ptr); |
133 | return *this; |
134 | } |
135 | |
136 | template<typename T> inline JSRetainPtr<T>& JSRetainPtr<T>::operator=(T optr) |
137 | { |
138 | if (optr) |
139 | JSRetain(optr); |
140 | if (T ptr = std::exchange(m_ptr, optr)) |
141 | JSRelease(ptr); |
142 | return *this; |
143 | } |
144 | |
145 | template<typename T> inline void JSRetainPtr<T>::swap(JSRetainPtr<T>& o) |
146 | { |
147 | std::swap(m_ptr, o.m_ptr); |
148 | } |
149 | |
150 | template<typename T> inline void swap(JSRetainPtr<T>& a, JSRetainPtr<T>& b) |
151 | { |
152 | a.swap(b); |
153 | } |
154 | |
155 | template<typename T, typename U> inline bool operator==(const JSRetainPtr<T>& a, const JSRetainPtr<U>& b) |
156 | { |
157 | return a.get() == b.get(); |
158 | } |
159 | |
160 | template<typename T, typename U> inline bool operator==(const JSRetainPtr<T>& a, U* b) |
161 | { |
162 | return a.get() == b; |
163 | } |
164 | |
165 | template<typename T, typename U> inline bool operator==(T* a, const JSRetainPtr<U>& b) |
166 | { |
167 | return a == b.get(); |
168 | } |
169 | |
170 | template<typename T, typename U> inline bool operator!=(const JSRetainPtr<T>& a, const JSRetainPtr<U>& b) |
171 | { |
172 | return a.get() != b.get(); |
173 | } |
174 | |
175 | template<typename T, typename U> inline bool operator!=(const JSRetainPtr<T>& a, U* b) |
176 | { |
177 | return a.get() != b; |
178 | } |
179 | |
180 | template<typename T, typename U> inline bool operator!=(T* a, const JSRetainPtr<U>& b) |
181 | { |
182 | return a != b.get(); |
183 | } |
184 | |