• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 are
6 * met:
7 *
8 *     * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *     * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 *     * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 
31 #ifndef V8Binding_h
32 #define V8Binding_h
33 
34 #include "BindingSecurity.h"
35 #include "MathExtras.h"
36 #include "PlatformString.h"
37 #include "V8DOMWrapper.h"
38 #include <wtf/text/AtomicString.h>
39 
40 #include <v8.h>
41 
42 namespace WebCore {
43 
44     class DOMStringList;
45     class EventListener;
46     class EventTarget;
47 
48     // FIXME: Remove V8Binding.
49     class V8Binding {
50     };
51     typedef BindingSecurity<V8Binding> V8BindingSecurity;
52 
53     enum ExternalMode {
54         Externalize,
55         DoNotExternalize
56     };
57 
58     template <typename StringType>
59     StringType v8StringToWebCoreString(v8::Handle<v8::String> v8String, ExternalMode external);
60 
61     // Convert v8 types to a WTF::String. If the V8 string is not already
62     // an external string then it is transformed into an external string at this
63     // point to avoid repeated conversions.
v8StringToWebCoreString(v8::Handle<v8::String> v8String)64     inline String v8StringToWebCoreString(v8::Handle<v8::String> v8String)
65     {
66         return v8StringToWebCoreString<String>(v8String, Externalize);
67     }
68     String v8NonStringValueToWebCoreString(v8::Handle<v8::Value>);
69     String v8ValueToWebCoreString(v8::Handle<v8::Value> value);
70 
71     // Convert v8 types to a WTF::AtomicString.
v8StringToAtomicWebCoreString(v8::Handle<v8::String> v8String)72     inline AtomicString v8StringToAtomicWebCoreString(v8::Handle<v8::String> v8String)
73     {
74         return v8StringToWebCoreString<AtomicString>(v8String, Externalize);
75     }
76     AtomicString v8NonStringValueToAtomicWebCoreString(v8::Handle<v8::Value>);
77     AtomicString v8ValueToAtomicWebCoreString(v8::Handle<v8::Value> value);
78 
79     // Note: RefPtr is a must as we cache by StringImpl* equality, not identity
80     // hence lastStringImpl might be not a key of the cache (in sense of identity)
81     // and hence it's not refed on addition.
82     extern RefPtr<StringImpl> lastStringImpl;
83     extern v8::Persistent<v8::String> lastV8String;
84     v8::Local<v8::String> v8ExternalStringSlow(StringImpl* stringImpl);
85 
86     // Return a V8 external string that shares the underlying buffer with the given
87     // WebCore string. The reference counting mechanism is used to keep the
88     // underlying buffer alive while the string is still live in the V8 engine.
v8ExternalString(const String & string)89     inline v8::Local<v8::String> v8ExternalString(const String& string)
90     {
91         StringImpl* stringImpl = string.impl();
92         if (!stringImpl)
93             return v8::String::Empty();
94 
95         if (lastStringImpl.get() == stringImpl) {
96             ASSERT(!lastV8String.IsNearDeath());
97             ASSERT(!lastV8String.IsEmpty());
98             return v8::Local<v8::String>::New(lastV8String);
99         }
100 
101         return v8ExternalStringSlow(stringImpl);
102     }
103 
104     // Convert a string to a V8 string.
v8String(const String & string)105     inline v8::Handle<v8::String> v8String(const String& string)
106     {
107         return v8ExternalString(string);
108     }
109 
110     // Enables caching v8 wrappers created for WTF::StringImpl.  Currently this cache requires
111     // all the calls (both to convert WTF::String to v8::String and to GC the handle)
112     // to be performed on the main thread.
113     void enableStringImplCache();
114 
115     // Convert a value to a 32-bit integer.  The conversion fails if the
116     // value cannot be converted to an integer or converts to nan or to an infinity.
117     int toInt32(v8::Handle<v8::Value> value, bool& ok);
118 
119     // Convert a value to a 32-bit integer assuming the conversion cannot fail.
toInt32(v8::Handle<v8::Value> value)120     inline int toInt32(v8::Handle<v8::Value> value)
121     {
122         bool ok;
123         return toInt32(value, ok);
124     }
125 
126     // Convert a value to a 32-bit unsigned integer.  The conversion fails if the
127     // value cannot be converted to an unsigned integer or converts to nan or to an infinity.
128     uint32_t toUInt32(v8::Handle<v8::Value> value, bool& ok);
129 
130     // Convert a value to a 32-bit unsigned integer assuming the conversion cannot fail.
toUInt32(v8::Handle<v8::Value> value)131     inline uint32_t toUInt32(v8::Handle<v8::Value> value)
132     {
133         bool ok;
134         return toUInt32(value, ok);
135     }
136 
toFloat(v8::Local<v8::Value> value)137     inline float toFloat(v8::Local<v8::Value> value)
138     {
139         return static_cast<float>(value->NumberValue());
140     }
141 
toInt64(v8::Local<v8::Value> value)142     inline long long toInt64(v8::Local<v8::Value> value)
143     {
144         return static_cast<long long>(value->IntegerValue());
145     }
146 
147     // FIXME: Drop this in favor of the type specific v8ValueToWebCoreString when we rework the code generation.
toWebCoreString(v8::Handle<v8::Value> object)148     inline String toWebCoreString(v8::Handle<v8::Value> object)
149     {
150         return v8ValueToWebCoreString(object);
151     }
152 
153     String toWebCoreString(const v8::Arguments&, int index);
154 
155     // The string returned by this function is still owned by the argument
156     // and will be deallocated when the argument is deallocated.
fromWebCoreString(const String & str)157     inline const uint16_t* fromWebCoreString(const String& str)
158     {
159         return reinterpret_cast<const uint16_t*>(str.characters());
160     }
161 
162     bool isUndefinedOrNull(v8::Handle<v8::Value> value);
163 
164     v8::Handle<v8::Boolean> v8Boolean(bool value);
165 
166     String toWebCoreStringWithNullCheck(v8::Handle<v8::Value> value);
167 
168     AtomicString toAtomicWebCoreStringWithNullCheck(v8::Handle<v8::Value> value);
169 
170     String toWebCoreStringWithNullOrUndefinedCheck(v8::Handle<v8::Value> value);
171 
172     v8::Handle<v8::String> v8UndetectableString(const String& str);
173 
174     v8::Handle<v8::Value> v8StringOrNull(const String& str);
175 
176     v8::Handle<v8::Value> v8StringOrUndefined(const String& str);
177 
178     v8::Handle<v8::Value> v8StringOrFalse(const String& str);
179 
180     double toWebCoreDate(v8::Handle<v8::Value> object);
181 
182     v8::Handle<v8::Value> v8DateOrNull(double value);
183 
184     v8::Persistent<v8::FunctionTemplate> createRawTemplate();
185 
186     struct BatchedAttribute;
187     struct BatchedCallback;
188 
189     v8::Local<v8::Signature> configureTemplate(v8::Persistent<v8::FunctionTemplate>,
190                                                const char* interfaceName,
191                                                v8::Persistent<v8::FunctionTemplate> parentClass,
192                                                int fieldCount,
193                                                const BatchedAttribute*,
194                                                size_t attributeCount,
195                                                const BatchedCallback*,
196                                                size_t callbackCount);
197 
198     v8::Handle<v8::Value> getElementStringAttr(const v8::AccessorInfo&,
199                                                const QualifiedName&);
200     void setElementStringAttr(const v8::AccessorInfo&,
201                               const QualifiedName&,
202                               v8::Local<v8::Value>);
203 
204 
205     v8::Persistent<v8::String> getToStringName();
206     v8::Persistent<v8::FunctionTemplate> getToStringTemplate();
207 
208     String int32ToWebCoreString(int value);
209 
210     PassRefPtr<DOMStringList> v8ValueToWebCoreDOMStringList(v8::Handle<v8::Value>);
211 
212     class V8ParameterBase {
213     public:
String()214         operator String() { return toString<String>(); }
AtomicString()215         operator AtomicString() { return toString<AtomicString>(); }
216 
217     protected:
V8ParameterBase(v8::Local<v8::Value> object)218         V8ParameterBase(v8::Local<v8::Value> object) : m_v8Object(object), m_mode(Externalize), m_string() { }
219 
prepareBase()220         bool prepareBase()
221         {
222             if (LIKELY(m_v8Object->IsString()))
223                 return true;
224 
225             if (LIKELY(m_v8Object->IsInt32())) {
226                 setString(int32ToWebCoreString(m_v8Object->Int32Value()));
227                 return true;
228             }
229 
230             m_mode = DoNotExternalize;
231             v8::TryCatch block;
232             m_v8Object = m_v8Object->ToString();
233             // Handle the case where an exception is thrown as part of invoking toString on the object.
234             if (block.HasCaught()) {
235                 block.ReThrow();
236                 return false;
237             }
238 
239             // This path is unexpected.  However there is hypothesis that it
240             // might be combination of v8 and v8 bindings bugs.  For now
241             // just bailout as we'll crash if attempt to convert empty handle into a string.
242             if (m_v8Object.IsEmpty()) {
243                 ASSERT_NOT_REACHED();
244                 return false;
245             }
246 
247             return true;
248         }
249 
object()250         v8::Local<v8::Value> object() { return m_v8Object; }
251 
setString(String string)252         void setString(String string)
253         {
254             m_string = string;
255             m_v8Object.Clear(); // To signal that String is ready.
256         }
257 
258      private:
259         v8::Local<v8::Value> m_v8Object;
260         ExternalMode m_mode;
261         String m_string;
262 
263         template <class StringType>
toString()264         StringType toString()
265         {
266             if (LIKELY(!m_v8Object.IsEmpty()))
267                 return v8StringToWebCoreString<StringType>(m_v8Object.As<v8::String>(), m_mode);
268 
269             return StringType(m_string);
270         }
271     };
272 
273     // V8Parameter is an adapter class that converts V8 values to Strings
274     // or AtomicStrings as appropriate, using multiple typecast operators.
275     enum V8ParameterMode {
276         DefaultMode,
277         WithNullCheck,
278         WithUndefinedOrNullCheck
279     };
280     template <V8ParameterMode MODE = DefaultMode>
281     class V8Parameter: public V8ParameterBase {
282     public:
V8Parameter(v8::Local<v8::Value> object)283         V8Parameter(v8::Local<v8::Value> object) : V8ParameterBase(object) { }
V8Parameter(v8::Local<v8::Value> object,bool)284         V8Parameter(v8::Local<v8::Value> object, bool) : V8ParameterBase(object) { prepare(); }
285 
286         bool prepare();
287     };
288 
prepare()289     template<> inline bool V8Parameter<DefaultMode>::prepare()
290     {
291         return V8ParameterBase::prepareBase();
292     }
293 
prepare()294     template<> inline bool V8Parameter<WithNullCheck>::prepare()
295     {
296         if (object()->IsNull()) {
297             setString(String());
298             return true;
299         }
300 
301         return V8ParameterBase::prepareBase();
302     }
303 
prepare()304     template<> inline bool V8Parameter<WithUndefinedOrNullCheck>::prepare()
305     {
306         if (object()->IsNull() || object()->IsUndefined()) {
307             setString(String());
308             return true;
309         }
310 
311         return V8ParameterBase::prepareBase();
312     }
313 
314 } // namespace WebCore
315 
316 #endif // V8Binding_h
317