OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 2009 Google 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. AND ITS CONTRIBUTORS ``AS IS'' | |
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | |
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS | |
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | |
23 * THE POSSIBILITY OF SUCH DAMAGE. | |
24 */ | |
25 | |
26 #ifndef V8StringResource_h | |
27 #define V8StringResource_h | |
28 | |
29 #include <v8.h> | |
30 #include "wtf/Threading.h" | |
31 #include "wtf/text/AtomicString.h" | |
32 #include "wtf/text/WTFString.h" | |
33 | |
34 namespace WebCore { | |
35 | |
36 class ExternalStringVisitor; | |
37 | |
38 // WebCoreStringResource is a helper class for v8ExternalString. It is used | |
39 // to manage the life-cycle of the underlying buffer of the external string. | |
40 class WebCoreStringResourceBase { | |
41 public: | |
42 explicit WebCoreStringResourceBase(const String& string) | |
43 : m_plainString(string) | |
44 { | |
45 #ifndef NDEBUG | |
46 m_threadId = WTF::currentThread(); | |
47 #endif | |
48 ASSERT(!string.isNull()); | |
49 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(memoryC
onsumption(string)); | |
50 } | |
51 | |
52 explicit WebCoreStringResourceBase(const AtomicString& string) | |
53 : m_plainString(string.string()) | |
54 , m_atomicString(string) | |
55 { | |
56 #ifndef NDEBUG | |
57 m_threadId = WTF::currentThread(); | |
58 #endif | |
59 ASSERT(!string.isNull()); | |
60 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(memoryC
onsumption(string)); | |
61 } | |
62 | |
63 virtual ~WebCoreStringResourceBase() | |
64 { | |
65 #ifndef NDEBUG | |
66 ASSERT(m_threadId == WTF::currentThread()); | |
67 #endif | |
68 int reducedExternalMemory = -memoryConsumption(m_plainString); | |
69 if (m_plainString.impl() != m_atomicString.impl() && !m_atomicString.isN
ull()) | |
70 reducedExternalMemory -= memoryConsumption(m_atomicString.string()); | |
71 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(reduced
ExternalMemory); | |
72 } | |
73 | |
74 const String& webcoreString() { return m_plainString; } | |
75 | |
76 const AtomicString& atomicString() | |
77 { | |
78 #ifndef NDEBUG | |
79 ASSERT(m_threadId == WTF::currentThread()); | |
80 #endif | |
81 if (m_atomicString.isNull()) { | |
82 m_atomicString = AtomicString(m_plainString); | |
83 ASSERT(!m_atomicString.isNull()); | |
84 if (m_plainString.impl() != m_atomicString.impl()) | |
85 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory
(memoryConsumption(m_atomicString.string())); | |
86 } | |
87 return m_atomicString; | |
88 } | |
89 | |
90 protected: | |
91 // A shallow copy of the string. Keeps the string buffer alive until the V8
engine garbage collects it. | |
92 String m_plainString; | |
93 // If this string is atomic or has been made atomic earlier the | |
94 // atomic string is held here. In the case where the string starts | |
95 // off non-atomic and becomes atomic later it is necessary to keep | |
96 // the original string alive because v8 may keep derived pointers | |
97 // into that string. | |
98 AtomicString m_atomicString; | |
99 | |
100 private: | |
101 static int memoryConsumption(const String& string) | |
102 { | |
103 return string.length() * (string.is8Bit() ? sizeof(LChar) : sizeof(UChar
)); | |
104 } | |
105 #ifndef NDEBUG | |
106 WTF::ThreadIdentifier m_threadId; | |
107 #endif | |
108 }; | |
109 | |
110 class WebCoreStringResource16 FINAL : public WebCoreStringResourceBase, public v
8::String::ExternalStringResource { | |
111 public: | |
112 explicit WebCoreStringResource16(const String& string) | |
113 : WebCoreStringResourceBase(string) | |
114 { | |
115 ASSERT(!string.is8Bit()); | |
116 } | |
117 | |
118 explicit WebCoreStringResource16(const AtomicString& string) | |
119 : WebCoreStringResourceBase(string) | |
120 { | |
121 ASSERT(!string.is8Bit()); | |
122 } | |
123 | |
124 virtual size_t length() const OVERRIDE { return m_plainString.impl()->length
(); } | |
125 virtual const uint16_t* data() const OVERRIDE | |
126 { | |
127 return reinterpret_cast<const uint16_t*>(m_plainString.impl()->character
s16()); | |
128 } | |
129 }; | |
130 | |
131 class WebCoreStringResource8 FINAL : public WebCoreStringResourceBase, public v8
::String::ExternalAsciiStringResource { | |
132 public: | |
133 explicit WebCoreStringResource8(const String& string) | |
134 : WebCoreStringResourceBase(string) | |
135 { | |
136 ASSERT(string.is8Bit()); | |
137 } | |
138 | |
139 explicit WebCoreStringResource8(const AtomicString& string) | |
140 : WebCoreStringResourceBase(string) | |
141 { | |
142 ASSERT(string.is8Bit()); | |
143 } | |
144 | |
145 virtual size_t length() const OVERRIDE { return m_plainString.impl()->length
(); } | |
146 virtual const char* data() const OVERRIDE | |
147 { | |
148 return reinterpret_cast<const char*>(m_plainString.impl()->characters8()
); | |
149 } | |
150 }; | |
151 | |
152 enum ExternalMode { | |
153 Externalize, | |
154 DoNotExternalize | |
155 }; | |
156 | |
157 template <typename StringType> | |
158 StringType v8StringToWebCoreString(v8::Handle<v8::String>, ExternalMode); | |
159 String int32ToWebCoreString(int value); | |
160 | |
161 // V8StringResource is an adapter class that converts V8 values to Strings | |
162 // or AtomicStrings as appropriate, using multiple typecast operators. | |
163 enum V8StringResourceMode { | |
164 DefaultMode, | |
165 WithNullCheck, | |
166 WithUndefinedOrNullCheck | |
167 }; | |
168 | |
169 template <V8StringResourceMode Mode = DefaultMode> | |
170 class V8StringResource { | |
171 public: | |
172 V8StringResource() | |
173 : m_mode(Externalize) | |
174 { | |
175 } | |
176 | |
177 V8StringResource(v8::Handle<v8::Value> object) | |
178 : m_v8Object(object) | |
179 , m_mode(Externalize) | |
180 { | |
181 } | |
182 | |
183 void operator=(v8::Handle<v8::Value> object) | |
184 { | |
185 m_v8Object = object; | |
186 } | |
187 | |
188 void operator=(const String& string) | |
189 { | |
190 setString(string); | |
191 } | |
192 | |
193 void operator=(std::nullptr_t) | |
194 { | |
195 setString(String()); | |
196 } | |
197 | |
198 bool prepare() | |
199 { | |
200 if (m_v8Object.IsEmpty()) | |
201 return true; | |
202 | |
203 if (!isValid()) { | |
204 setString(String()); | |
205 return true; | |
206 } | |
207 | |
208 if (LIKELY(m_v8Object->IsString())) | |
209 return true; | |
210 | |
211 if (LIKELY(m_v8Object->IsInt32())) { | |
212 setString(int32ToWebCoreString(m_v8Object->Int32Value())); | |
213 return true; | |
214 } | |
215 | |
216 m_mode = DoNotExternalize; | |
217 v8::TryCatch block; | |
218 m_v8Object = m_v8Object->ToString(); | |
219 // Handle the case where an exception is thrown as part of invoking toSt
ring on the object. | |
220 if (block.HasCaught()) { | |
221 block.ReThrow(); | |
222 return false; | |
223 } | |
224 return true; | |
225 } | |
226 operator String() const { return toString<String>(); } | |
227 operator AtomicString() const { return toString<AtomicString>(); } | |
228 | |
229 private: | |
230 bool isValid() const; | |
231 | |
232 void setString(const String& string) | |
233 { | |
234 m_string = string; | |
235 m_v8Object.Clear(); // To signal that String is ready. | |
236 } | |
237 | |
238 template <class StringType> | |
239 StringType toString() const | |
240 { | |
241 if (LIKELY(!m_v8Object.IsEmpty())) | |
242 return v8StringToWebCoreString<StringType>(const_cast<v8::Handle<v8:
:Value>*>(&m_v8Object)->As<v8::String>(), m_mode); | |
243 | |
244 return StringType(m_string); | |
245 } | |
246 | |
247 v8::Handle<v8::Value> m_v8Object; | |
248 ExternalMode m_mode; | |
249 String m_string; | |
250 }; | |
251 | |
252 template<> inline bool V8StringResource<DefaultMode>::isValid() const | |
253 { | |
254 return true; | |
255 } | |
256 | |
257 template<> inline bool V8StringResource<WithNullCheck>::isValid() const | |
258 { | |
259 return !m_v8Object->IsNull(); | |
260 } | |
261 | |
262 template<> inline bool V8StringResource<WithUndefinedOrNullCheck>::isValid() con
st | |
263 { | |
264 return !m_v8Object->IsNull() && !m_v8Object->IsUndefined(); | |
265 } | |
266 | |
267 } // namespace WebCore | |
268 | |
269 #endif // V8StringResource_h | |
OLD | NEW |