summaryrefslogtreecommitdiffstats
path: root/webkit/port/bindings/v8/v8_binding.cpp
blob: 616d7b2fad4dec2ac526234a7cd49eab073c56bd (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
121
122
123
124
125
126
127
128
129
130
// 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, bool externalize) {
  WebCoreStringResource* str_resource = static_cast<WebCoreStringResource*>(
      v8_str->GetExternalStringResource());
  if (str_resource) {
    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 StringImpl::empty();
  }

  UChar* buffer;
  String result = String::createUninitialized(length, buffer);
  v8_str->Write(reinterpret_cast<uint16_t*>(buffer), 0, length);

  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<v8::Value> obj) {
  if (obj->IsString()) {
    v8::Handle<v8::String> v8_str = v8::Handle<v8::String>::Cast(obj);
    String webCoreString = v8StringToWebCoreString(v8_str, true);
    return webCoreString;
  } else if (obj->IsInt32()) {
    int value = obj->Int32Value();
    // Most numbers used are <= 100. Even if they aren't used
    // there's very little in using the space.
    const int kLowNumbers = 100;
    static 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;
  } else {
    v8::TryCatch block;
    v8::Handle<v8::String> v8_str = obj->ToString();
    // Check for empty handles to handle the case where an exception
    // is thrown as part of invoking toString on the object.
    if (v8_str.IsEmpty())
      return StringImpl::empty();
    return v8StringToWebCoreString(v8_str, false);
  }
}


AtomicString v8StringToAtomicWebCoreString(v8::Handle<v8::String> v8_str) {
  String str = v8StringToWebCoreString(v8_str, true);
  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