summaryrefslogtreecommitdiffstats
path: root/V8Binding/v8/v8_binding.cpp
blob: 3a36fc514404840ac3d74de9e1e81e6c97c0d40b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// 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