/*
* Copyright (C) 2009 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef V8Binding_h
#define V8Binding_h
#include "BindingSecurity.h"
#include "MathExtras.h"
#include "PlatformString.h"
#include "V8DOMWrapper.h"
#include <wtf/text/AtomicString.h>
#include <v8.h>
namespace WebCore {
class DOMStringList;
class EventListener;
class EventTarget;
// FIXME: Remove V8Binding.
class V8Binding {
};
typedef BindingSecurity<V8Binding> V8BindingSecurity;
enum ExternalMode {
Externalize,
DoNotExternalize
};
template <typename StringType>
StringType v8StringToWebCoreString(v8::Handle<v8::String> v8String, ExternalMode external);
// Convert v8 types to a WTF::String. If the V8 string is not already
// an external string then it is transformed into an external string at this
// point to avoid repeated conversions.
inline String v8StringToWebCoreString(v8::Handle<v8::String> v8String)
{
return v8StringToWebCoreString<String>(v8String, Externalize);
}
String v8NonStringValueToWebCoreString(v8::Handle<v8::Value>);
String v8ValueToWebCoreString(v8::Handle<v8::Value> value);
// Convert v8 types to a WTF::AtomicString.
inline AtomicString v8StringToAtomicWebCoreString(v8::Handle<v8::String> v8String)
{
return v8StringToWebCoreString<AtomicString>(v8String, Externalize);
}
AtomicString v8NonStringValueToAtomicWebCoreString(v8::Handle<v8::Value>);
AtomicString v8ValueToAtomicWebCoreString(v8::Handle<v8::Value> value);
// Note: RefPtr is a must as we cache by StringImpl* equality, not identity
// hence lastStringImpl might be not a key of the cache (in sense of identity)
// and hence it's not refed on addition.
extern RefPtr<StringImpl> lastStringImpl;
extern v8::Persistent<v8::String> lastV8String;
v8::Local<v8::String> v8ExternalStringSlow(StringImpl* stringImpl);
// Return a V8 external string that shares the underlying buffer with the given
// WebCore string. The reference counting mechanism is used to keep the
// underlying buffer alive while the string is still live in the V8 engine.
inline v8::Local<v8::String> v8ExternalString(const String& string)
{
StringImpl* stringImpl = string.impl();
if (!stringImpl)
return v8::String::Empty();
if (lastStringImpl.get() == stringImpl) {
ASSERT(!lastV8String.IsNearDeath());
ASSERT(!lastV8String.IsEmpty());
return v8::Local<v8::String>::New(lastV8String);
}
return v8ExternalStringSlow(stringImpl);
}
// Convert a string to a V8 string.
inline v8::Handle<v8::String> v8String(const String& string)
{
return v8ExternalString(string);
}
// Enables caching v8 wrappers created for WTF::StringImpl. Currently this cache requires
// all the calls (both to convert WTF::String to v8::String and to GC the handle)
// to be performed on the main thread.
void enableStringImplCache();
// Convert a value to a 32-bit integer. The conversion fails if the
// value cannot be converted to an integer or converts to nan or to an infinity.
int toInt32(v8::Handle<v8::Value> value, bool& ok);
// Convert a value to a 32-bit integer assuming the conversion cannot fail.
inline int toInt32(v8::Handle<v8::Value> value)
{
bool ok;
return toInt32(value, ok);
}
// Convert a value to a 32-bit unsigned integer. The conversion fails if the
// value cannot be converted to an unsigned integer or converts to nan or to an infinity.
uint32_t toUInt32(v8::Handle<v8::Value> value, bool& ok);
// Convert a value to a 32-bit unsigned integer assuming the conversion cannot fail.
inline uint32_t toUInt32(v8::Handle<v8::Value> value)
{
bool ok;
return toUInt32(value, ok);
}
inline float toFloat(v8::Local<v8::Value> value)
{
return static_cast<float>(value->NumberValue());
}
inline long long toInt64(v8::Local<v8::Value> value)
{
return static_cast<long long>(value->IntegerValue());
}
// FIXME: Drop this in favor of the type specific v8ValueToWebCoreString when we rework the code generation.
inline String toWebCoreString(v8::Handle<v8::Value> object)
{
return v8ValueToWebCoreString(object);
}
String toWebCoreString(const v8::Arguments&, int index);
// The string returned by this function is still owned by the argument
// and will be deallocated when the argument is deallocated.
inline const uint16_t* fromWebCoreString(const String& str)
{
return reinterpret_cast<const uint16_t*>(str.characters());
}
bool isUndefinedOrNull(v8::Handle<v8::Value> value);
v8::Handle<v8::Boolean> v8Boolean(bool value);
String toWebCoreStringWithNullCheck(v8::Handle<v8::Value> value);
AtomicString toAtomicWebCoreStringWithNullCheck(v8::Handle<v8::Value> value);
String toWebCoreStringWithNullOrUndefinedCheck(v8::Handle<v8::Value> value);
v8::Handle<v8::String> v8UndetectableString(const String& str);
v8::Handle<v8::Value> v8StringOrNull(const String& str);
v8::Handle<v8::Value> v8StringOrUndefined(const String& str);
v8::Handle<v8::Value> v8StringOrFalse(const String& str);
double toWebCoreDate(v8::Handle<v8::Value> object);
v8::Handle<v8::Value> v8DateOrNull(double value);
v8::Persistent<v8::FunctionTemplate> createRawTemplate();
struct BatchedAttribute;
struct BatchedCallback;
v8::Local<v8::Signature> configureTemplate(v8::Persistent<v8::FunctionTemplate>,
const char* interfaceName,
v8::Persistent<v8::FunctionTemplate> parentClass,
int fieldCount,
const BatchedAttribute*,
size_t attributeCount,
const BatchedCallback*,
size_t callbackCount);
v8::Handle<v8::Value> getElementStringAttr(const v8::AccessorInfo&,
const QualifiedName&);
void setElementStringAttr(const v8::AccessorInfo&,
const QualifiedName&,
v8::Local<v8::Value>);
v8::Persistent<v8::String> getToStringName();
v8::Persistent<v8::FunctionTemplate> getToStringTemplate();
String int32ToWebCoreString(int value);
PassRefPtr<DOMStringList> v8ValueToWebCoreDOMStringList(v8::Handle<v8::Value>);
class V8ParameterBase {
public:
operator String() { return toString<String>(); }
operator AtomicString() { return toString<AtomicString>(); }
protected:
V8ParameterBase(v8::Local<v8::Value> object) : m_v8Object(object), m_mode(Externalize), m_string() { }
bool prepareBase()
{
if (LIKELY(m_v8Object->IsString()))
return true;
if (LIKELY(m_v8Object->IsInt32())) {
setString(int32ToWebCoreString(m_v8Object->Int32Value()));
return true;
}
m_mode = DoNotExternalize;
v8::TryCatch block;
m_v8Object = m_v8Object->ToString();
// Handle the case where an exception is thrown as part of invoking toString on the object.
if (block.HasCaught()) {
block.ReThrow();
return false;
}
// This path is unexpected. However there is hypothesis that it
// might be combination of v8 and v8 bindings bugs. For now
// just bailout as we'll crash if attempt to convert empty handle into a string.
if (m_v8Object.IsEmpty()) {
ASSERT_NOT_REACHED();
return false;
}
return true;
}
v8::Local<v8::Value> object() { return m_v8Object; }
void setString(String string)
{
m_string = string;
m_v8Object.Clear(); // To signal that String is ready.
}
private:
v8::Local<v8::Value> m_v8Object;
ExternalMode m_mode;
String m_string;
template <class StringType>
StringType toString()
{
if (LIKELY(!m_v8Object.IsEmpty()))
return v8StringToWebCoreString<StringType>(m_v8Object.As<v8::String>(), m_mode);
return StringType(m_string);
}
};
// V8Parameter is an adapter class that converts V8 values to Strings
// or AtomicStrings as appropriate, using multiple typecast operators.
enum V8ParameterMode {
DefaultMode,
WithNullCheck,
WithUndefinedOrNullCheck
};
template <V8ParameterMode MODE = DefaultMode>
class V8Parameter: public V8ParameterBase {
public:
V8Parameter(v8::Local<v8::Value> object) : V8ParameterBase(object) { }
V8Parameter(v8::Local<v8::Value> object, bool) : V8ParameterBase(object) { prepare(); }
bool prepare();
};
template<> inline bool V8Parameter<DefaultMode>::prepare()
{
return V8ParameterBase::prepareBase();
}
template<> inline bool V8Parameter<WithNullCheck>::prepare()
{
if (object()->IsNull()) {
setString(String());
return true;
}
return V8ParameterBase::prepareBase();
}
template<> inline bool V8Parameter<WithUndefinedOrNullCheck>::prepare()
{
if (object()->IsNull() || object()->IsUndefined()) {
setString(String());
return true;
}
return V8ParameterBase::prepareBase();
}
} // namespace WebCore
#endif // V8Binding_h