// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "v8_binding.h" #include "AtomicString.h" #include "CString.h" #include "MathExtras.h" #include "PlatformString.h" #include "StringBuffer.h" #include 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& str) : impl_(str.impl()) { } virtual ~WebCoreStringResource() {} const uint16_t* data() const { return reinterpret_cast(impl_.characters()); } size_t length() const { return impl_.length(); } String webcore_string() { return impl_; } private: // A shallow copy of the string. // Keeps the string buffer alive until the V8 engine garbage collects it. String impl_; }; String v8StringToWebCoreString( v8::Handle v8_str, bool externalize) { if (v8_str->IsExternal()) { WebCoreStringResource* str_resource = static_cast( v8_str->GetExternalStringResource()); return str_resource->webcore_string(); } int length = v8_str->Length(); if (length == 0) { // Avoid trying to morph empty strings, as they do not have enough room to // contain the external reference. return ""; } // Copy the characters from the v8::String into a WebCore::String and allocate // an external resource which will be attached to the v8::String. String result; const int kStringSizeToCopy = 256; if (length < kStringSizeToCopy) { uint16_t buffer[kStringSizeToCopy]; v8_str->Write(buffer, 0, length); result = StringImpl::create(reinterpret_cast(buffer), length); } else { StringBuffer buf(length); v8_str->Write(reinterpret_cast(buf.characters()), 0, length); result = String::adopt(buf); } // // TODO(mbelshe): Disable string morphing because it causes mystery // perf regressions on intl1 and intl2 page cyclers. It works fine // on machines other than the buildbots. if (externalize) { WebCoreStringResource* resource = new WebCoreStringResource(result); if (!v8_str->MakeExternal(resource)) { // In case of a failure delete the external resource as it was not used. delete resource; } } return result; } String v8ValueToWebCoreString(v8::Handle obj) { v8::Handle v8_str; if (obj->IsString()) { v8_str = v8::Handle::Cast(obj); return v8StringToWebCoreString(v8_str, true); } else { v8::TryCatch block; v8_str = obj->ToString(); if (v8_str.IsEmpty()) return ""; } return v8StringToWebCoreString(v8_str, false); } AtomicString v8StringToAtomicWebCoreString(v8::Handle v8_str) { String str = v8StringToWebCoreString(v8_str, true); return AtomicString(str); } AtomicString v8ValueToAtomicWebCoreString(v8::Handle v8_str) { String str = v8ValueToWebCoreString(v8_str); return AtomicString(str); } v8::Handle v8String(const String& str) { if (!str.length()) return v8::String::Empty(); return v8::String::NewExternal(new WebCoreStringResource(str)); } v8::Local v8ExternalString(const String& str) { if (!str.length()) return v8::String::Empty(); return v8::String::NewExternal(new WebCoreStringResource(str)); } } // namespace WebCore