Home | History | Annotate | Download | only in extensions
      1 // Copyright 2010 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/extensions/externalize-string-extension.h"
      6 
      7 namespace v8 {
      8 namespace internal {
      9 
     10 template <typename Char, typename Base>
     11 class SimpleStringResource : public Base {
     12  public:
     13   // Takes ownership of |data|.
     14   SimpleStringResource(Char* data, size_t length)
     15       : data_(data),
     16         length_(length) {}
     17 
     18   virtual ~SimpleStringResource() { delete[] data_; }
     19 
     20   virtual const Char* data() const { return data_; }
     21 
     22   virtual size_t length() const { return length_; }
     23 
     24  private:
     25   Char* const data_;
     26   const size_t length_;
     27 };
     28 
     29 
     30 typedef SimpleStringResource<char, v8::String::ExternalAsciiStringResource>
     31     SimpleAsciiStringResource;
     32 typedef SimpleStringResource<uc16, v8::String::ExternalStringResource>
     33     SimpleTwoByteStringResource;
     34 
     35 
     36 const char* const ExternalizeStringExtension::kSource =
     37     "native function externalizeString();"
     38     "native function isAsciiString();";
     39 
     40 v8::Handle<v8::FunctionTemplate>
     41 ExternalizeStringExtension::GetNativeFunctionTemplate(
     42     v8::Isolate* isolate, v8::Handle<v8::String> str) {
     43   if (strcmp(*v8::String::Utf8Value(str), "externalizeString") == 0) {
     44     return v8::FunctionTemplate::New(isolate,
     45                                      ExternalizeStringExtension::Externalize);
     46   } else {
     47     ASSERT(strcmp(*v8::String::Utf8Value(str), "isAsciiString") == 0);
     48     return v8::FunctionTemplate::New(isolate,
     49                                      ExternalizeStringExtension::IsAscii);
     50   }
     51 }
     52 
     53 
     54 void ExternalizeStringExtension::Externalize(
     55     const v8::FunctionCallbackInfo<v8::Value>& args) {
     56   if (args.Length() < 1 || !args[0]->IsString()) {
     57     args.GetIsolate()->ThrowException(v8::String::NewFromUtf8(
     58         args.GetIsolate(),
     59         "First parameter to externalizeString() must be a string."));
     60     return;
     61   }
     62   bool force_two_byte = false;
     63   if (args.Length() >= 2) {
     64     if (args[1]->IsBoolean()) {
     65       force_two_byte = args[1]->BooleanValue();
     66     } else {
     67       args.GetIsolate()->ThrowException(v8::String::NewFromUtf8(
     68         args.GetIsolate(),
     69         "Second parameter to externalizeString() must be a boolean."));
     70       return;
     71     }
     72   }
     73   bool result = false;
     74   Handle<String> string = Utils::OpenHandle(*args[0].As<v8::String>());
     75   if (string->IsExternalString()) {
     76     args.GetIsolate()->ThrowException(v8::String::NewFromUtf8(
     77         args.GetIsolate(),
     78         "externalizeString() can't externalize twice."));
     79     return;
     80   }
     81   if (string->IsOneByteRepresentation() && !force_two_byte) {
     82     uint8_t* data = new uint8_t[string->length()];
     83     String::WriteToFlat(*string, data, 0, string->length());
     84     SimpleAsciiStringResource* resource = new SimpleAsciiStringResource(
     85         reinterpret_cast<char*>(data), string->length());
     86     result = string->MakeExternal(resource);
     87     if (result) {
     88       i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate());
     89       isolate->heap()->external_string_table()->AddString(*string);
     90     }
     91     if (!result) delete resource;
     92   } else {
     93     uc16* data = new uc16[string->length()];
     94     String::WriteToFlat(*string, data, 0, string->length());
     95     SimpleTwoByteStringResource* resource = new SimpleTwoByteStringResource(
     96         data, string->length());
     97     result = string->MakeExternal(resource);
     98     if (result) {
     99       i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate());
    100       isolate->heap()->external_string_table()->AddString(*string);
    101     }
    102     if (!result) delete resource;
    103   }
    104   if (!result) {
    105     args.GetIsolate()->ThrowException(v8::String::NewFromUtf8(
    106         args.GetIsolate(), "externalizeString() failed."));
    107     return;
    108   }
    109 }
    110 
    111 
    112 void ExternalizeStringExtension::IsAscii(
    113     const v8::FunctionCallbackInfo<v8::Value>& args) {
    114   if (args.Length() != 1 || !args[0]->IsString()) {
    115     args.GetIsolate()->ThrowException(v8::String::NewFromUtf8(
    116         args.GetIsolate(),
    117         "isAsciiString() requires a single string argument."));
    118     return;
    119   }
    120   bool is_one_byte =
    121       Utils::OpenHandle(*args[0].As<v8::String>())->IsOneByteRepresentation();
    122   args.GetReturnValue().Set(is_one_byte);
    123 }
    124 
    125 } }  // namespace v8::internal
    126