diff options
Diffstat (limited to 'WebCore/bindings/v8/V8Binding.cpp')
-rw-r--r-- | WebCore/bindings/v8/V8Binding.cpp | 581 |
1 files changed, 0 insertions, 581 deletions
diff --git a/WebCore/bindings/v8/V8Binding.cpp b/WebCore/bindings/v8/V8Binding.cpp deleted file mode 100644 index 52b23bd..0000000 --- a/WebCore/bindings/v8/V8Binding.cpp +++ /dev/null @@ -1,581 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008, 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. - */ - -#include "config.h" -#include "V8Binding.h" - -#include "Element.h" -#include "MathExtras.h" -#include "PlatformString.h" -#include "QualifiedName.h" -#include "StdLibExtras.h" -#include "Threading.h" -#include "V8Element.h" -#include "V8Proxy.h" -#include <wtf/text/AtomicString.h> -#include <wtf/text/CString.h> -#include <wtf/text/StringBuffer.h> -#include <wtf/text/StringHash.h> - -namespace WebCore { - -// WebCoreStringResource is a helper class for v8ExternalString. It is used -// to manage the life-cycle of the underlying buffer of the external string. -class WebCoreStringResource : public v8::String::ExternalStringResource { -public: - explicit WebCoreStringResource(const String& string) - : m_plainString(string) - { -#ifndef NDEBUG - m_threadId = WTF::currentThread(); -#endif - ASSERT(!string.isNull()); - v8::V8::AdjustAmountOfExternalAllocatedMemory(2 * string.length()); - } - - explicit WebCoreStringResource(const AtomicString& string) - : m_plainString(string.string()) - , m_atomicString(string) - { -#ifndef NDEBUG - m_threadId = WTF::currentThread(); -#endif - ASSERT(!string.isNull()); - v8::V8::AdjustAmountOfExternalAllocatedMemory(2 * string.length()); - } - - virtual ~WebCoreStringResource() - { -#ifndef NDEBUG - ASSERT(m_threadId == WTF::currentThread()); -#endif - int reducedExternalMemory = -2 * m_plainString.length(); - if (m_plainString.impl() != m_atomicString.impl() && !m_atomicString.isNull()) - reducedExternalMemory *= 2; - v8::V8::AdjustAmountOfExternalAllocatedMemory(reducedExternalMemory); - } - - virtual const uint16_t* data() const - { - return reinterpret_cast<const uint16_t*>(m_plainString.impl()->characters()); - } - - virtual size_t length() const { return m_plainString.impl()->length(); } - - String webcoreString() { return m_plainString; } - - AtomicString atomicString() - { -#ifndef NDEBUG - ASSERT(m_threadId == WTF::currentThread()); -#endif - if (m_atomicString.isNull()) { - m_atomicString = AtomicString(m_plainString); - ASSERT(!m_atomicString.isNull()); - if (m_plainString.impl() != m_atomicString.impl()) - v8::V8::AdjustAmountOfExternalAllocatedMemory(2 * m_atomicString.length()); - } - return m_atomicString; - } - - static WebCoreStringResource* toStringResource(v8::Handle<v8::String> v8String) - { - return static_cast<WebCoreStringResource*>(v8String->GetExternalStringResource()); - } - -private: - // A shallow copy of the string. Keeps the string buffer alive until the V8 engine garbage collects it. - String m_plainString; - // If this string is atomic or has been made atomic earlier the - // atomic string is held here. In the case where the string starts - // off non-atomic and becomes atomic later it is necessary to keep - // the original string alive because v8 may keep derived pointers - // into that string. - AtomicString m_atomicString; - -#ifndef NDEBUG - WTF::ThreadIdentifier m_threadId; -#endif -}; - -String v8ValueToWebCoreString(v8::Handle<v8::Value> value) -{ - if (value->IsString()) - return v8StringToWebCoreString(v8::Handle<v8::String>::Cast(value)); - return v8NonStringValueToWebCoreString(value); -} - -AtomicString v8ValueToAtomicWebCoreString(v8::Handle<v8::Value> value) -{ - if (value->IsString()) - return v8StringToAtomicWebCoreString(v8::Handle<v8::String>::Cast(value)); - return v8NonStringValueToAtomicWebCoreString(value); -} - -int toInt32(v8::Handle<v8::Value> value, bool& ok) -{ - ok = true; - - // Fast case. The value is already a 32-bit integer. - if (value->IsInt32()) - return value->Int32Value(); - - // Can the value be converted to a number? - v8::Local<v8::Number> numberObject = value->ToNumber(); - if (numberObject.IsEmpty()) { - ok = false; - return 0; - } - - // Does the value convert to nan or to an infinity? - double numberValue = numberObject->Value(); - if (isnan(numberValue) || isinf(numberValue)) { - ok = false; - return 0; - } - - // Can the value be converted to a 32-bit integer? - v8::Local<v8::Int32> intValue = value->ToInt32(); - if (intValue.IsEmpty()) { - ok = false; - return 0; - } - - // Return the result of the int32 conversion. - return intValue->Value(); -} - -uint32_t toUInt32(v8::Handle<v8::Value> value, bool& ok) -{ - ok = true; - - // FIXME: there is currently no Value::IsUint32(). This code does - // some contortions to avoid silently converting out-of-range - // values to uint32_t. - - // Fast case. The value is already a 32-bit positive integer. - if (value->IsInt32()) { - int32_t result = value->Int32Value(); - if (result >= 0) - return result; - } - - // Can the value be converted to a number? - v8::Local<v8::Number> numberObject = value->ToNumber(); - if (numberObject.IsEmpty()) { - ok = false; - return 0; - } - - // Does the value convert to nan or to an infinity? - double numberValue = numberObject->Value(); - if (isnan(numberValue) || isinf(numberValue)) { - ok = false; - return 0; - } - - // Can the value be converted to a 32-bit unsigned integer? - v8::Local<v8::Uint32> uintValue = value->ToUint32(); - if (uintValue.IsEmpty()) { - ok = false; - return 0; - } - - // FIXME: v8::Uint32::Value is not defined! - // http://code.google.com/p/v8/issues/detail?id=624 - v8::Local<v8::Int32> intValue = value->ToInt32(); - if (intValue.IsEmpty()) { - ok = false; - return 0; - } - - return static_cast<uint32_t>(intValue->Value()); -} - -String toWebCoreString(const v8::Arguments& args, int index) { - return v8ValueToWebCoreString(args[index]); -} - - -String toWebCoreStringWithNullCheck(v8::Handle<v8::Value> value) -{ - if (value->IsNull()) - return String(); - return v8ValueToWebCoreString(value); -} - -AtomicString toAtomicWebCoreStringWithNullCheck(v8::Handle<v8::Value> value) -{ - if (value->IsNull()) - return AtomicString(); - return v8ValueToAtomicWebCoreString(value); -} - -String toWebCoreStringWithNullOrUndefinedCheck(v8::Handle<v8::Value> value) -{ - if (value->IsNull() || value->IsUndefined()) - return String(); - return toWebCoreString(value); -} - -bool isUndefinedOrNull(v8::Handle<v8::Value> value) -{ - return value->IsNull() || value->IsUndefined(); -} - -v8::Handle<v8::Boolean> v8Boolean(bool value) -{ - return value ? v8::True() : v8::False(); -} - -v8::Handle<v8::String> v8UndetectableString(const String& str) -{ - return v8::String::NewUndetectable(fromWebCoreString(str), str.length()); -} - -v8::Handle<v8::Value> v8StringOrNull(const String& str) -{ - return str.isNull() ? v8::Handle<v8::Value>(v8::Null()) : v8::Handle<v8::Value>(v8String(str)); -} - -v8::Handle<v8::Value> v8StringOrUndefined(const String& str) -{ - return str.isNull() ? v8::Handle<v8::Value>(v8::Undefined()) : v8::Handle<v8::Value>(v8String(str)); -} - -v8::Handle<v8::Value> v8StringOrFalse(const String& str) -{ - return str.isNull() ? v8::Handle<v8::Value>(v8::False()) : v8::Handle<v8::Value>(v8String(str)); -} - -double toWebCoreDate(v8::Handle<v8::Value> object) -{ - return (object->IsDate() || object->IsNumber()) ? object->NumberValue() : std::numeric_limits<double>::quiet_NaN(); -} - -v8::Handle<v8::Value> v8DateOrNull(double value) -{ - if (isfinite(value)) - return v8::Date::New(value); - return v8::Null(); -} - -template <class S> struct StringTraits -{ - static S fromStringResource(WebCoreStringResource* resource); - - static S fromV8String(v8::Handle<v8::String> v8String, int length); -}; - -template<> -struct StringTraits<String> -{ - static String fromStringResource(WebCoreStringResource* resource) - { - return resource->webcoreString(); - } - - static String fromV8String(v8::Handle<v8::String> v8String, int length) - { - ASSERT(v8String->Length() == length); - // NOTE: as of now, String(const UChar*, int) performs String::createUninitialized - // anyway, so no need to optimize like we do for AtomicString below. - UChar* buffer; - String result = String::createUninitialized(length, buffer); - v8String->Write(reinterpret_cast<uint16_t*>(buffer), 0, length); - return result; - } -}; - -template<> -struct StringTraits<AtomicString> -{ - static AtomicString fromStringResource(WebCoreStringResource* resource) - { - return resource->atomicString(); - } - - static AtomicString fromV8String(v8::Handle<v8::String> v8String, int length) - { - ASSERT(v8String->Length() == length); - static const int inlineBufferSize = 16; - if (length <= inlineBufferSize) { - UChar inlineBuffer[inlineBufferSize]; - v8String->Write(reinterpret_cast<uint16_t*>(inlineBuffer), 0, length); - return AtomicString(inlineBuffer, length); - } - UChar* buffer; - String tmp = String::createUninitialized(length, buffer); - v8String->Write(reinterpret_cast<uint16_t*>(buffer), 0, length); - return AtomicString(tmp); - } -}; - -template <typename StringType> -StringType v8StringToWebCoreString(v8::Handle<v8::String> v8String, ExternalMode external) -{ - WebCoreStringResource* stringResource = WebCoreStringResource::toStringResource(v8String); - if (stringResource) - return StringTraits<StringType>::fromStringResource(stringResource); - - int length = v8String->Length(); - if (!length) { - // Avoid trying to morph empty strings, as they do not have enough room to contain the external reference. - return StringImpl::empty(); - } - - StringType result(StringTraits<StringType>::fromV8String(v8String, length)); - - if (external == Externalize && v8String->CanMakeExternal()) { - stringResource = new WebCoreStringResource(result); - if (!v8String->MakeExternal(stringResource)) { - // In case of a failure delete the external resource as it was not used. - delete stringResource; - } - } - return result; -} - -// Explicitly instantiate the above template with the expected parameterizations, -// to ensure the compiler generates the code; otherwise link errors can result in GCC 4.4. -template String v8StringToWebCoreString<String>(v8::Handle<v8::String>, ExternalMode); -template AtomicString v8StringToWebCoreString<AtomicString>(v8::Handle<v8::String>, ExternalMode); - -// Fast but non thread-safe version. -String int32ToWebCoreStringFast(int value) -{ - // Caching of small strings below is not thread safe: newly constructed AtomicString - // are not safely published. - ASSERT(WTF::isMainThread()); - - // Most numbers used are <= 100. Even if they aren't used there's very little cost in using the space. - const int kLowNumbers = 100; - DEFINE_STATIC_LOCAL(Vector<AtomicString>, lowNumbers, (kLowNumbers + 1)); - String webCoreString; - if (0 <= value && value <= kLowNumbers) { - webCoreString = lowNumbers[value]; - if (!webCoreString) { - AtomicString valueString = AtomicString(String::number(value)); - lowNumbers[value] = valueString; - webCoreString = valueString; - } - } else - webCoreString = String::number(value); - return webCoreString; -} - -String int32ToWebCoreString(int value) -{ - // If we are on the main thread (this should always true for non-workers), call the faster one. - if (WTF::isMainThread()) - return int32ToWebCoreStringFast(value); - return String::number(value); -} - -String v8NonStringValueToWebCoreString(v8::Handle<v8::Value> object) -{ - ASSERT(!object->IsString()); - if (object->IsInt32()) - return int32ToWebCoreString(object->Int32Value()); - - v8::TryCatch block; - v8::Handle<v8::String> v8String = object->ToString(); - // Handle the case where an exception is thrown as part of invoking toString on the object. - if (block.HasCaught()) { - throwError(block.Exception()); - return StringImpl::empty(); - } - return v8StringToWebCoreString<String>(v8String, DoNotExternalize); -} - -AtomicString v8NonStringValueToAtomicWebCoreString(v8::Handle<v8::Value> object) -{ - ASSERT(!object->IsString()); - return AtomicString(v8NonStringValueToWebCoreString(object)); -} - -static bool stringImplCacheEnabled = false; - -void enableStringImplCache() -{ - stringImplCacheEnabled = true; -} - -static v8::Local<v8::String> makeExternalString(const String& string) -{ - WebCoreStringResource* stringResource = new WebCoreStringResource(string); - v8::Local<v8::String> newString = v8::String::NewExternal(stringResource); - if (newString.IsEmpty()) - delete stringResource; - - return newString; -} - -typedef HashMap<StringImpl*, v8::String*> StringCache; - -static StringCache& getStringCache() -{ - ASSERT(WTF::isMainThread()); - DEFINE_STATIC_LOCAL(StringCache, mainThreadStringCache, ()); - return mainThreadStringCache; -} - -static void cachedStringCallback(v8::Persistent<v8::Value> wrapper, void* parameter) -{ - ASSERT(WTF::isMainThread()); - StringImpl* stringImpl = static_cast<StringImpl*>(parameter); - ASSERT(getStringCache().contains(stringImpl)); - getStringCache().remove(stringImpl); - wrapper.Dispose(); - stringImpl->deref(); -} - -RefPtr<StringImpl> lastStringImpl = 0; -v8::Persistent<v8::String> lastV8String; - -v8::Local<v8::String> v8ExternalStringSlow(StringImpl* stringImpl) -{ - if (!stringImpl->length()) - return v8::String::Empty(); - - if (!stringImplCacheEnabled) - return makeExternalString(String(stringImpl)); - - StringCache& stringCache = getStringCache(); - v8::String* cachedV8String = stringCache.get(stringImpl); - if (cachedV8String) { - v8::Persistent<v8::String> handle(cachedV8String); - if (!handle.IsNearDeath() && !handle.IsEmpty()) { - lastStringImpl = stringImpl; - lastV8String = handle; - return v8::Local<v8::String>::New(handle); - } - } - - v8::Local<v8::String> newString = makeExternalString(String(stringImpl)); - if (newString.IsEmpty()) - return newString; - - v8::Persistent<v8::String> wrapper = v8::Persistent<v8::String>::New(newString); - if (wrapper.IsEmpty()) - return newString; - - stringImpl->ref(); - wrapper.MakeWeak(stringImpl, cachedStringCallback); - stringCache.set(stringImpl, *wrapper); - - lastStringImpl = stringImpl; - lastV8String = wrapper; - - return newString; -} - -v8::Persistent<v8::FunctionTemplate> createRawTemplate() -{ - v8::HandleScope scope; - v8::Local<v8::FunctionTemplate> result = v8::FunctionTemplate::New(V8Proxy::checkNewLegal); - return v8::Persistent<v8::FunctionTemplate>::New(result); -} - -v8::Local<v8::Signature> configureTemplate(v8::Persistent<v8::FunctionTemplate> desc, - const char *interfaceName, - v8::Persistent<v8::FunctionTemplate> parentClass, - int fieldCount, - const BatchedAttribute* attributes, - size_t attributeCount, - const BatchedCallback* callbacks, - size_t callbackCount) -{ - desc->SetClassName(v8::String::New(interfaceName)); - v8::Local<v8::ObjectTemplate> instance = desc->InstanceTemplate(); - instance->SetInternalFieldCount(fieldCount); - if (!parentClass.IsEmpty()) - desc->Inherit(parentClass); - if (attributeCount) - batchConfigureAttributes(instance, desc->PrototypeTemplate(), - attributes, attributeCount); - v8::Local<v8::Signature> defaultSignature = v8::Signature::New(desc); - if (callbackCount) - batchConfigureCallbacks(desc->PrototypeTemplate(), - defaultSignature, - static_cast<v8::PropertyAttribute>(v8::DontDelete), - callbacks, callbackCount); - return defaultSignature; -} - -v8::Persistent<v8::String> getToStringName() -{ - DEFINE_STATIC_LOCAL(v8::Persistent<v8::String>, value, ()); - if (value.IsEmpty()) - value = v8::Persistent<v8::String>::New(v8::String::New("toString")); - return value; -} - -static v8::Handle<v8::Value> constructorToString(const v8::Arguments& args) -{ - // The DOM constructors' toString functions grab the current toString - // for Functions by taking the toString function of itself and then - // calling it with the constructor as its receiver. This means that - // changes to the Function prototype chain or toString function are - // reflected when printing DOM constructors. The only wart is that - // changes to a DOM constructor's toString's toString will cause the - // toString of the DOM constructor itself to change. This is extremely - // obscure and unlikely to be a problem. - v8::Handle<v8::Value> value = args.Callee()->Get(getToStringName()); - if (!value->IsFunction()) - return v8::String::New(""); - return v8::Handle<v8::Function>::Cast(value)->Call(args.This(), 0, 0); -} - -v8::Persistent<v8::FunctionTemplate> getToStringTemplate() -{ - DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, toStringTemplate, ()); - if (toStringTemplate.IsEmpty()) - toStringTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(constructorToString)); - return toStringTemplate; -} - -v8::Handle<v8::Value> getElementStringAttr(const v8::AccessorInfo& info, - const QualifiedName& name) -{ - Element* imp = V8Element::toNative(info.Holder()); - return v8ExternalString(imp->getAttribute(name)); -} - -void setElementStringAttr(const v8::AccessorInfo& info, - const QualifiedName& name, - v8::Local<v8::Value> value) -{ - Element* imp = V8Element::toNative(info.Holder()); - AtomicString v = toAtomicWebCoreStringWithNullCheck(value); - imp->setAttribute(name, v); -} - -} // namespace WebCore |