1// Copyright 2010 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "externalize-string-extension.h"
29
30namespace v8 {
31namespace internal {
32
33template <typename Char, typename Base>
34class SimpleStringResource : public Base {
35 public:
36  // Takes ownership of |data|.
37  SimpleStringResource(Char* data, size_t length)
38      : data_(data),
39        length_(length) {}
40
41  virtual ~SimpleStringResource() { delete[] data_; }
42
43  virtual const Char* data() const { return data_; }
44
45  virtual size_t length() const { return length_; }
46
47 private:
48  Char* const data_;
49  const size_t length_;
50};
51
52
53typedef SimpleStringResource<char, v8::String::ExternalAsciiStringResource>
54    SimpleAsciiStringResource;
55typedef SimpleStringResource<uc16, v8::String::ExternalStringResource>
56    SimpleTwoByteStringResource;
57
58
59const char* const ExternalizeStringExtension::kSource =
60    "native function externalizeString();"
61    "native function isAsciiString();";
62
63
64v8::Handle<v8::FunctionTemplate> ExternalizeStringExtension::GetNativeFunction(
65    v8::Handle<v8::String> str) {
66  if (strcmp(*v8::String::AsciiValue(str), "externalizeString") == 0) {
67    return v8::FunctionTemplate::New(ExternalizeStringExtension::Externalize);
68  } else {
69    ASSERT(strcmp(*v8::String::AsciiValue(str), "isAsciiString") == 0);
70    return v8::FunctionTemplate::New(ExternalizeStringExtension::IsAscii);
71  }
72}
73
74
75v8::Handle<v8::Value> ExternalizeStringExtension::Externalize(
76    const v8::Arguments& args) {
77  if (args.Length() < 1 || !args[0]->IsString()) {
78    return v8::ThrowException(v8::String::New(
79        "First parameter to externalizeString() must be a string."));
80  }
81  bool force_two_byte = false;
82  if (args.Length() >= 2) {
83    if (args[1]->IsBoolean()) {
84      force_two_byte = args[1]->BooleanValue();
85    } else {
86      return v8::ThrowException(v8::String::New(
87          "Second parameter to externalizeString() must be a boolean."));
88    }
89  }
90  bool result = false;
91  Handle<String> string = Utils::OpenHandle(*args[0].As<v8::String>());
92  if (string->IsExternalString()) {
93    return v8::ThrowException(v8::String::New(
94        "externalizeString() can't externalize twice."));
95  }
96  if (string->IsAsciiRepresentation() && !force_two_byte) {
97    char* data = new char[string->length()];
98    String::WriteToFlat(*string, data, 0, string->length());
99    SimpleAsciiStringResource* resource = new SimpleAsciiStringResource(
100        data, string->length());
101    result = string->MakeExternal(resource);
102    if (result && !string->IsSymbol()) {
103      HEAP->external_string_table()->AddString(*string);
104    }
105    if (!result) delete resource;
106  } else {
107    uc16* data = new uc16[string->length()];
108    String::WriteToFlat(*string, data, 0, string->length());
109    SimpleTwoByteStringResource* resource = new SimpleTwoByteStringResource(
110        data, string->length());
111    result = string->MakeExternal(resource);
112    if (result && !string->IsSymbol()) {
113      HEAP->external_string_table()->AddString(*string);
114    }
115    if (!result) delete resource;
116  }
117  if (!result) {
118    return v8::ThrowException(v8::String::New("externalizeString() failed."));
119  }
120  return v8::Undefined();
121}
122
123
124v8::Handle<v8::Value> ExternalizeStringExtension::IsAscii(
125    const v8::Arguments& args) {
126  if (args.Length() != 1 || !args[0]->IsString()) {
127    return v8::ThrowException(v8::String::New(
128        "isAsciiString() requires a single string argument."));
129  }
130  return Utils::OpenHandle(*args[0].As<v8::String>())->IsAsciiRepresentation() ?
131      v8::True() : v8::False();
132}
133
134
135void ExternalizeStringExtension::Register() {
136  static ExternalizeStringExtension* externalize_extension = NULL;
137  if (externalize_extension == NULL)
138    externalize_extension = new ExternalizeStringExtension;
139  static v8::DeclareExtension externalize_extension_declaration(
140      externalize_extension);
141}
142
143} }  // namespace v8::internal
144