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