Home | History | Annotate | Download | only in v8
      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.
     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.
     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.
     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.
    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.
    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.
    131     inline uint32_t toUInt32(v8::Handle<v8::Value> value)
    132     {
    133         bool ok;
    134         return toUInt32(value, ok);
    135     }
    136 
    137     inline float toFloat(v8::Local<v8::Value> value)
    138     {
    139         return static_cast<float>(value->NumberValue());
    140     }
    141 
    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.
    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.
    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:
    214         operator String() { return toString<String>(); }
    215         operator AtomicString() { return toString<AtomicString>(); }
    216 
    217     protected:
    218         V8ParameterBase(v8::Local<v8::Value> object) : m_v8Object(object), m_mode(Externalize), m_string() { }
    219 
    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 
    250         v8::Local<v8::Value> object() { return m_v8Object; }
    251 
    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>
    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:
    283         V8Parameter(v8::Local<v8::Value> object) : V8ParameterBase(object) { }
    284         V8Parameter(v8::Local<v8::Value> object, bool) : V8ParameterBase(object) { prepare(); }
    285 
    286         bool prepare();
    287     };
    288 
    289     template<> inline bool V8Parameter<DefaultMode>::prepare()
    290     {
    291         return V8ParameterBase::prepareBase();
    292     }
    293 
    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 
    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