blob: 3a36fc514404840ac3d74de9e1e81e6c97c0d40b [file] [log] [blame]
// 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 <v8.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& str)
: impl_(str.impl()) { }
virtual ~WebCoreStringResource() {}
const uint16_t* data() const {
return reinterpret_cast<const uint16_t*>(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::String> v8_str) {
if (v8_str->IsExternal()) {
WebCoreStringResource* str_resource = static_cast<WebCoreStringResource*>(
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<UChar*>(buffer), length);
} else {
StringBuffer buf(length);
v8_str->Write(reinterpret_cast<uint16_t*>(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.
//
// 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<v8::Value> obj) {
v8::Handle<v8::String> v8_str;
if (obj->IsString()) {
v8_str = v8::Handle<v8::String>::Cast(obj);
} else {
v8::TryCatch block;
v8_str = obj->ToString();
if (v8_str.IsEmpty())
return "";
}
return v8StringToWebCoreString(v8_str);
}
AtomicString v8StringToAtomicWebCoreString(v8::Handle<v8::String> v8_str) {
String str = v8StringToWebCoreString(v8_str);
return AtomicString(str);
}
AtomicString v8ValueToAtomicWebCoreString(v8::Handle<v8::Value> v8_str) {
String str = v8ValueToWebCoreString(v8_str);
return AtomicString(str);
}
v8::Handle<v8::String> v8String(const String& str) {
if (!str.length())
return v8::String::Empty();
return v8::String::NewExternal(new WebCoreStringResource(str));
}
v8::Local<v8::String> v8ExternalString(const String& str) {
if (!str.length())
return v8::String::Empty();
return v8::String::NewExternal(new WebCoreStringResource(str));
}
} // namespace WebCore