Commit 943d5cc2 authored by jochen@chromium.org's avatar jochen@chromium.org

Move i18n break iterator C++ code to runtime

BUG=v8:2745
R=mstarzinger@chromium.org

Review URL: https://codereview.chromium.org/22764007

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16239 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent f86f275f
This diff is collapsed.
// Copyright 2013 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// limitations under the License.
#ifndef V8_EXTENSIONS_I18N_BREAK_ITERATOR_H_
#define V8_EXTENSIONS_I18N_BREAK_ITERATOR_H_
#include "unicode/uversion.h"
#include "v8.h"
namespace U_ICU_NAMESPACE {
class BreakIterator;
class UnicodeString;
}
namespace v8_i18n {
class BreakIterator {
public:
static void JSCreateBreakIterator(
const v8::FunctionCallbackInfo<v8::Value>& args);
// Helper methods for various bindings.
// Unpacks iterator object from corresponding JavaScript object.
static icu::BreakIterator* UnpackBreakIterator(v8::Handle<v8::Object> obj);
// Release memory we allocated for the BreakIterator once the JS object that
// holds the pointer gets garbage collected.
static void DeleteBreakIterator(v8::Isolate* isolate,
v8::Persistent<v8::Object>* object,
void* param);
// Assigns new text to the iterator.
static void JSInternalBreakIteratorAdoptText(
const v8::FunctionCallbackInfo<v8::Value>& args);
// Moves iterator to the beginning of the string and returns new position.
static void JSInternalBreakIteratorFirst(
const v8::FunctionCallbackInfo<v8::Value>& args);
// Moves iterator to the next position and returns it.
static void JSInternalBreakIteratorNext(
const v8::FunctionCallbackInfo<v8::Value>& args);
// Returns current iterator's current position.
static void JSInternalBreakIteratorCurrent(
const v8::FunctionCallbackInfo<v8::Value>& args);
// Returns type of the item from current position.
// This call is only valid for word break iterators. Others just return 0.
static void JSInternalBreakIteratorBreakType(
const v8::FunctionCallbackInfo<v8::Value>& args);
private:
BreakIterator() {}
};
} // namespace v8_i18n
#endif // V8_EXTENSIONS_I18N_BREAK_ITERATOR_H_
......@@ -35,8 +35,6 @@
* Useful for subclassing.
*/
function initializeBreakIterator(iterator, locales, options) {
native function NativeJSCreateBreakIterator();
if (iterator.hasOwnProperty('__initializedIntlObject')) {
throw new TypeError('Trying to re-initialize v8BreakIterator object.');
}
......@@ -59,9 +57,9 @@ function initializeBreakIterator(iterator, locales, options) {
locale: {writable: true}
});
var internalIterator = NativeJSCreateBreakIterator(locale.locale,
internalOptions,
resolved);
var internalIterator = %CreateBreakIterator(locale.locale,
internalOptions,
resolved);
Object.defineProperty(iterator, 'iterator', {value: internalIterator});
Object.defineProperty(iterator, 'resolved', {value: resolved});
......@@ -149,8 +147,7 @@ function initializeBreakIterator(iterator, locales, options) {
* gets discarded.
*/
function adoptText(iterator, text) {
native function NativeJSBreakIteratorAdoptText();
NativeJSBreakIteratorAdoptText(iterator.iterator, String(text));
%BreakIteratorAdoptText(iterator.iterator, String(text));
}
......@@ -158,8 +155,7 @@ function adoptText(iterator, text) {
* Returns index of the first break in the string and moves current pointer.
*/
function first(iterator) {
native function NativeJSBreakIteratorFirst();
return NativeJSBreakIteratorFirst(iterator.iterator);
return %BreakIteratorFirst(iterator.iterator);
}
......@@ -167,8 +163,7 @@ function first(iterator) {
* Returns the index of the next break and moves the pointer.
*/
function next(iterator) {
native function NativeJSBreakIteratorNext();
return NativeJSBreakIteratorNext(iterator.iterator);
return %BreakIteratorNext(iterator.iterator);
}
......@@ -176,8 +171,7 @@ function next(iterator) {
* Returns index of the current break.
*/
function current(iterator) {
native function NativeJSBreakIteratorCurrent();
return NativeJSBreakIteratorCurrent(iterator.iterator);
return %BreakIteratorCurrent(iterator.iterator);
}
......@@ -185,8 +179,7 @@ function current(iterator) {
* Returns type of the current break.
*/
function breakType(iterator) {
native function NativeJSBreakIteratorBreakType();
return NativeJSBreakIteratorBreakType(iterator.iterator);
return %BreakIteratorBreakType(iterator.iterator);
}
......
......@@ -28,7 +28,6 @@
#include "i18n-extension.h"
#include "break-iterator.h"
#include "natives.h"
using v8::internal::I18NNatives;
......@@ -43,31 +42,6 @@ Extension::Extension()
0,
I18NNatives::GetScriptsSource().length()) {}
v8::Handle<v8::FunctionTemplate> Extension::GetNativeFunction(
v8::Handle<v8::String> name) {
// Break iterator.
if (name->Equals(v8::String::New("NativeJSCreateBreakIterator"))) {
return v8::FunctionTemplate::New(BreakIterator::JSCreateBreakIterator);
} else if (name->Equals(v8::String::New("NativeJSBreakIteratorAdoptText"))) {
return v8::FunctionTemplate::New(
BreakIterator::JSInternalBreakIteratorAdoptText);
} else if (name->Equals(v8::String::New("NativeJSBreakIteratorFirst"))) {
return v8::FunctionTemplate::New(
BreakIterator::JSInternalBreakIteratorFirst);
} else if (name->Equals(v8::String::New("NativeJSBreakIteratorNext"))) {
return v8::FunctionTemplate::New(
BreakIterator::JSInternalBreakIteratorNext);
} else if (name->Equals(v8::String::New("NativeJSBreakIteratorCurrent"))) {
return v8::FunctionTemplate::New(
BreakIterator::JSInternalBreakIteratorCurrent);
} else if (name->Equals(v8::String::New("NativeJSBreakIteratorBreakType"))) {
return v8::FunctionTemplate::New(
BreakIterator::JSInternalBreakIteratorBreakType);
}
return v8::Handle<v8::FunctionTemplate>();
}
void Extension::Register() {
static Extension i18n_extension;
......
......@@ -37,9 +37,6 @@ class Extension : public v8::Extension {
public:
Extension();
virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
v8::Handle<v8::String> name);
static void Register();
private:
......
// Copyright 2013 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// limitations under the License.
#include "i18n-utils.h"
#include <string.h>
#include "unicode/unistr.h"
namespace v8_i18n {
// static
void Utils::StrNCopy(char* dest, int length, const char* src) {
if (!dest || !src) return;
strncpy(dest, src, length);
dest[length - 1] = '\0';
}
// static
bool Utils::V8StringToUnicodeString(const v8::Handle<v8::Value>& input,
icu::UnicodeString* output) {
v8::String::Utf8Value utf8_value(input);
if (*utf8_value == NULL) return false;
output->setTo(icu::UnicodeString::fromUTF8(*utf8_value));
return true;
}
// static
bool Utils::ExtractStringSetting(const v8::Handle<v8::Object>& settings,
const char* setting,
icu::UnicodeString* result) {
if (!setting || !result) return false;
v8::HandleScope handle_scope;
v8::TryCatch try_catch;
v8::Handle<v8::Value> value = settings->Get(v8::String::New(setting));
if (try_catch.HasCaught()) {
return false;
}
// No need to check if |value| is empty because it's taken care of
// by TryCatch above.
if (!value->IsUndefined() && !value->IsNull() && value->IsString()) {
return V8StringToUnicodeString(value, result);
}
return false;
}
// static
bool Utils::ExtractIntegerSetting(const v8::Handle<v8::Object>& settings,
const char* setting,
int32_t* result) {
if (!setting || !result) return false;
v8::HandleScope handle_scope;
v8::TryCatch try_catch;
v8::Handle<v8::Value> value = settings->Get(v8::String::New(setting));
if (try_catch.HasCaught()) {
return false;
}
// No need to check if |value| is empty because it's taken care of
// by TryCatch above.
if (!value->IsUndefined() && !value->IsNull() && value->IsNumber()) {
*result = static_cast<int32_t>(value->Int32Value());
return true;
}
return false;
}
// static
bool Utils::ExtractBooleanSetting(const v8::Handle<v8::Object>& settings,
const char* setting,
bool* result) {
if (!setting || !result) return false;
v8::HandleScope handle_scope;
v8::TryCatch try_catch;
v8::Handle<v8::Value> value = settings->Get(v8::String::New(setting));
if (try_catch.HasCaught()) {
return false;
}
// No need to check if |value| is empty because it's taken care of
// by TryCatch above.
if (!value->IsUndefined() && !value->IsNull() && value->IsBoolean()) {
*result = static_cast<bool>(value->BooleanValue());
return true;
}
return false;
}
// static
void Utils::AsciiToUChar(const char* source,
int32_t source_length,
UChar* target,
int32_t target_length) {
int32_t length =
source_length < target_length ? source_length : target_length;
if (length <= 0) {
return;
}
for (int32_t i = 0; i < length - 1; ++i) {
target[i] = static_cast<UChar>(source[i]);
}
target[length - 1] = 0x0u;
}
static v8::Local<v8::ObjectTemplate> ToLocal(i::Handle<i::Object> handle) {
return v8::Utils::ToLocal(i::Handle<i::ObjectTemplateInfo>::cast(handle));
}
template<int internal_fields, i::EternalHandles::SingletonHandle field>
static v8::Local<v8::ObjectTemplate> GetEternal(v8::Isolate* external) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external);
if (isolate->eternal_handles()->Exists(field)) {
return ToLocal(isolate->eternal_handles()->GetSingleton(field));
}
v8::Local<v8::ObjectTemplate> raw_template(v8::ObjectTemplate::New());
raw_template->SetInternalFieldCount(internal_fields);
return ToLocal(
isolate->eternal_handles()->CreateSingleton(
isolate,
*v8::Utils::OpenHandle(*raw_template),
field));
}
// static
v8::Local<v8::ObjectTemplate> Utils::GetTemplate(v8::Isolate* isolate) {
return GetEternal<1, i::EternalHandles::I18N_TEMPLATE_ONE>(isolate);
}
// static
v8::Local<v8::ObjectTemplate> Utils::GetTemplate2(v8::Isolate* isolate) {
return GetEternal<2, i::EternalHandles::I18N_TEMPLATE_TWO>(isolate);
}
} // namespace v8_i18n
// Copyright 2013 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// limitations under the License.
#ifndef V8_EXTENSIONS_I18N_SRC_UTILS_H_
#define V8_EXTENSIONS_I18N_SRC_UTILS_H_
#include "unicode/uversion.h"
#include "v8.h"
namespace U_ICU_NAMESPACE {
class UnicodeString;
}
namespace v8_i18n {
class Utils {
public:
// Safe string copy. Null terminates the destination. Copies at most
// (length - 1) bytes.
// We can't use snprintf since it's not supported on all relevant platforms.
// We can't use OS::SNPrintF, it's only for internal code.
static void StrNCopy(char* dest, int length, const char* src);
// Converts v8::String into UnicodeString. Returns false if input
// can't be converted into utf8.
static bool V8StringToUnicodeString(const v8::Handle<v8::Value>& input,
icu::UnicodeString* output);
// Extract a String setting named in |settings| and set it to |result|.
// Return true if it's specified. Otherwise, return false.
static bool ExtractStringSetting(const v8::Handle<v8::Object>& settings,
const char* setting,
icu::UnicodeString* result);
// Extract a Integer setting named in |settings| and set it to |result|.
// Return true if it's specified. Otherwise, return false.
static bool ExtractIntegerSetting(const v8::Handle<v8::Object>& settings,
const char* setting,
int32_t* result);
// Extract a Boolean setting named in |settings| and set it to |result|.
// Return true if it's specified. Otherwise, return false.
static bool ExtractBooleanSetting(const v8::Handle<v8::Object>& settings,
const char* setting,
bool* result);
// Converts ASCII array into UChar array.
// Target is always \0 terminated.
static void AsciiToUChar(const char* source,
int32_t source_length,
UChar* target,
int32_t target_length);
// Creates an ObjectTemplate with one internal field.
static v8::Local<v8::ObjectTemplate> GetTemplate(v8::Isolate* isolate);
// Creates an ObjectTemplate with two internal fields.
static v8::Local<v8::ObjectTemplate> GetTemplate2(v8::Isolate* isolate);
private:
Utils() {}
};
} // namespace v8_i18n
#endif // V8_EXTENSIONS_I18N_UTILS_H_
......@@ -28,6 +28,7 @@
#include "i18n.h"
#include "unicode/brkiter.h"
#include "unicode/calendar.h"
#include "unicode/coll.h"
#include "unicode/curramt.h"
......@@ -38,6 +39,7 @@
#include "unicode/locid.h"
#include "unicode/numfmt.h"
#include "unicode/numsys.h"
#include "unicode/rbbi.h"
#include "unicode/smpdtfmt.h"
#include "unicode/timezone.h"
#include "unicode/uchar.h"
......@@ -731,6 +733,69 @@ void SetResolvedCollatorSettings(Isolate* isolate,
}
}
icu::BreakIterator* CreateICUBreakIterator(
Isolate* isolate,
const icu::Locale& icu_locale,
Handle<JSObject> options) {
UErrorCode status = U_ZERO_ERROR;
icu::BreakIterator* break_iterator = NULL;
icu::UnicodeString type;
if (!ExtractStringSetting(isolate, options, "type", &type)) return NULL;
if (type == UNICODE_STRING_SIMPLE("character")) {
break_iterator =
icu::BreakIterator::createCharacterInstance(icu_locale, status);
} else if (type == UNICODE_STRING_SIMPLE("sentence")) {
break_iterator =
icu::BreakIterator::createSentenceInstance(icu_locale, status);
} else if (type == UNICODE_STRING_SIMPLE("line")) {
break_iterator =
icu::BreakIterator::createLineInstance(icu_locale, status);
} else {
// Defualt is word iterator.
break_iterator =
icu::BreakIterator::createWordInstance(icu_locale, status);
}
if (U_FAILURE(status)) {
delete break_iterator;
return NULL;
}
return break_iterator;
}
void SetResolvedBreakIteratorSettings(Isolate* isolate,
const icu::Locale& icu_locale,
icu::BreakIterator* break_iterator,
Handle<JSObject> resolved) {
UErrorCode status = U_ZERO_ERROR;
// Set the locale
char result[ULOC_FULLNAME_CAPACITY];
status = U_ZERO_ERROR;
uloc_toLanguageTag(
icu_locale.getName(), result, ULOC_FULLNAME_CAPACITY, FALSE, &status);
if (U_SUCCESS(status)) {
JSObject::SetProperty(
resolved,
isolate->factory()->NewStringFromAscii(CStrVector("locale")),
isolate->factory()->NewStringFromAscii(CStrVector(result)),
NONE,
kNonStrictMode);
} else {
// This would never happen, since we got the locale from ICU.
JSObject::SetProperty(
resolved,
isolate->factory()->NewStringFromAscii(CStrVector("locale")),
isolate->factory()->NewStringFromAscii(CStrVector("und")),
NONE,
kNonStrictMode);
}
}
} // namespace
......@@ -935,4 +1000,71 @@ void Collator::DeleteCollator(v8::Isolate* isolate,
object->Dispose(isolate);
}
icu::BreakIterator* BreakIterator::InitializeBreakIterator(
Isolate* isolate,
Handle<String> locale,
Handle<JSObject> options,
Handle<JSObject> resolved) {
// Convert BCP47 into ICU locale format.
UErrorCode status = U_ZERO_ERROR;
icu::Locale icu_locale;
char icu_result[ULOC_FULLNAME_CAPACITY];
int icu_length = 0;
v8::String::Utf8Value bcp47_locale(v8::Utils::ToLocal(locale));
if (bcp47_locale.length() != 0) {
uloc_forLanguageTag(*bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY,
&icu_length, &status);
if (U_FAILURE(status) || icu_length == 0) {
return NULL;
}
icu_locale = icu::Locale(icu_result);
}
icu::BreakIterator* break_iterator = CreateICUBreakIterator(
isolate, icu_locale, options);
if (!break_iterator) {
// Remove extensions and try again.
icu::Locale no_extension_locale(icu_locale.getBaseName());
break_iterator = CreateICUBreakIterator(
isolate, no_extension_locale, options);
// Set resolved settings (locale).
SetResolvedBreakIteratorSettings(
isolate, no_extension_locale, break_iterator, resolved);
} else {
SetResolvedBreakIteratorSettings(
isolate, icu_locale, break_iterator, resolved);
}
return break_iterator;
}
icu::BreakIterator* BreakIterator::UnpackBreakIterator(Isolate* isolate,
Handle<JSObject> obj) {
Handle<String> key =
isolate->factory()->NewStringFromAscii(CStrVector("breakIterator"));
if (obj->HasLocalProperty(*key)) {
return reinterpret_cast<icu::BreakIterator*>(obj->GetInternalField(0));
}
return NULL;
}
void BreakIterator::DeleteBreakIterator(v8::Isolate* isolate,
Persistent<v8::Value>* object,
void* param) {
// First delete the hidden C++ object.
delete reinterpret_cast<icu::BreakIterator*>(Handle<JSObject>::cast(
v8::Utils::OpenPersistent(object))->GetInternalField(0));
delete reinterpret_cast<icu::UnicodeString*>(Handle<JSObject>::cast(
v8::Utils::OpenPersistent(object))->GetInternalField(1));
// Then dispose of the persistent handle to JS object.
object->Dispose(isolate);
}
} } // namespace v8::internal
......@@ -33,6 +33,7 @@
#include "v8.h"
namespace U_ICU_NAMESPACE {
class BreakIterator;
class Collator;
class DecimalFormat;
class SimpleDateFormat;
......@@ -124,6 +125,30 @@ class Collator {
Collator();
};
class BreakIterator {
public:
// Create a BreakIterator for the specificied locale and options. Returns the
// resolved settings for the locale / options.
static icu::BreakIterator* InitializeBreakIterator(
Isolate* isolate,
Handle<String> locale,
Handle<JSObject> options,
Handle<JSObject> resolved);
// Unpacks break iterator object from corresponding JavaScript object.
static icu::BreakIterator* UnpackBreakIterator(Isolate* isolate,
Handle<JSObject> obj);
// Release memory we allocated for the BreakIterator once the JS object that
// holds the pointer gets garbage collected.
static void DeleteBreakIterator(v8::Isolate* isolate,
Persistent<v8::Value>* object,
void* param);
private:
BreakIterator();
};
} } // namespace v8::internal
#endif // V8_I18N_H_
......@@ -80,6 +80,7 @@
#include "unicode/locid.h"
#include "unicode/numfmt.h"
#include "unicode/numsys.h"
#include "unicode/rbbi.h"
#include "unicode/smpdtfmt.h"
#include "unicode/timezone.h"
#include "unicode/uchar.h"
......@@ -13879,6 +13880,158 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalCompare) {
return *isolate->factory()->NewNumberFromInt(result);
}
RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateBreakIterator) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
Handle<ObjectTemplateInfo> break_iterator_template =
I18N::GetTemplate2(isolate);
// Create an empty object wrapper.
bool has_pending_exception = false;
Handle<JSObject> local_object = Execution::InstantiateObject(
break_iterator_template, &has_pending_exception);
if (has_pending_exception) {
ASSERT(isolate->has_pending_exception());
return Failure::Exception();
}
// Set break iterator as internal field of the resulting JS object.
icu::BreakIterator* break_iterator = BreakIterator::InitializeBreakIterator(
isolate, locale, options, resolved);
if (!break_iterator) return isolate->ThrowIllegalOperation();
local_object->SetInternalField(0, reinterpret_cast<Smi*>(break_iterator));
// Make sure that the pointer to adopted text is NULL.
local_object->SetInternalField(1, reinterpret_cast<Smi*>(NULL));
RETURN_IF_EMPTY_HANDLE(isolate,
JSObject::SetLocalPropertyIgnoreAttributes(
local_object,
isolate->factory()->NewStringFromAscii(CStrVector("breakIterator")),
isolate->factory()->NewStringFromAscii(CStrVector("valid")),
NONE));
// Make object handle weak so we can delete the break iterator once GC kicks
// in.
Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
GlobalHandles::MakeWeak(reinterpret_cast<Object**>(wrapper.location()),
NULL,
BreakIterator::DeleteBreakIterator);
return *local_object;
}
RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorAdoptText) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
CONVERT_ARG_HANDLE_CHECKED(String, text, 1);
icu::BreakIterator* break_iterator =
BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
if (!break_iterator) return isolate->ThrowIllegalOperation();
icu::UnicodeString* u_text = reinterpret_cast<icu::UnicodeString*>(
break_iterator_holder->GetInternalField(1));
delete u_text;
v8::String::Value text_value(v8::Utils::ToLocal(text));
u_text = new icu::UnicodeString(
reinterpret_cast<const UChar*>(*text_value), text_value.length());
break_iterator_holder->SetInternalField(1, reinterpret_cast<Smi*>(u_text));
break_iterator->setText(*u_text);
return isolate->heap()->undefined_value();
}
RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorFirst) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
icu::BreakIterator* break_iterator =
BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
if (!break_iterator) return isolate->ThrowIllegalOperation();
return *isolate->factory()->NewNumberFromInt(break_iterator->first());
}
RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorNext) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
icu::BreakIterator* break_iterator =
BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
if (!break_iterator) return isolate->ThrowIllegalOperation();
return *isolate->factory()->NewNumberFromInt(break_iterator->next());
}
RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorCurrent) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
icu::BreakIterator* break_iterator =
BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
if (!break_iterator) return isolate->ThrowIllegalOperation();
return *isolate->factory()->NewNumberFromInt(break_iterator->current());
}
RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorBreakType) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
icu::BreakIterator* break_iterator =
BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
if (!break_iterator) return isolate->ThrowIllegalOperation();
// TODO(cira): Remove cast once ICU fixes base BreakIterator class.
icu::RuleBasedBreakIterator* rule_based_iterator =
static_cast<icu::RuleBasedBreakIterator*>(break_iterator);
int32_t status = rule_based_iterator->getRuleStatus();
// Keep return values in sync with JavaScript BreakType enum.
if (status >= UBRK_WORD_NONE && status < UBRK_WORD_NONE_LIMIT) {
return *isolate->factory()->NewStringFromAscii(CStrVector("none"));
} else if (status >= UBRK_WORD_NUMBER && status < UBRK_WORD_NUMBER_LIMIT) {
return *isolate->factory()->NewStringFromAscii(CStrVector("number"));
} else if (status >= UBRK_WORD_LETTER && status < UBRK_WORD_LETTER_LIMIT) {
return *isolate->factory()->NewStringFromAscii(CStrVector("letter"));
} else if (status >= UBRK_WORD_KANA && status < UBRK_WORD_KANA_LIMIT) {
return *isolate->factory()->NewStringFromAscii(CStrVector("kana"));
} else if (status >= UBRK_WORD_IDEO && status < UBRK_WORD_IDEO_LIMIT) {
return *isolate->factory()->NewStringFromAscii(CStrVector("ideo"));
} else {
return *isolate->factory()->NewStringFromAscii(CStrVector("unknown"));
}
}
#endif // V8_I18N_SUPPORT
......
......@@ -558,6 +558,14 @@ namespace internal {
/* Collator. */ \
F(CreateCollator, 3, 1) \
F(InternalCompare, 3, 1) \
\
/* Break iterator. */ \
F(CreateBreakIterator, 3, 1) \
F(BreakIteratorAdoptText, 2, 1) \
F(BreakIteratorFirst, 1, 1) \
F(BreakIteratorNext, 1, 1) \
F(BreakIteratorCurrent, 1, 1) \
F(BreakIteratorBreakType, 1, 1) \
#else
#define RUNTIME_FUNCTION_LIST_I18N_SUPPORT(F)
......
......@@ -380,6 +380,8 @@
'../../src/hydrogen-uint32-analysis.h',
'../../src/hydrogen-osr.cc',
'../../src/hydrogen-osr.h',
'../../src/i18n.cc',
'../../src/i18n.h',
'../../src/icu_util.cc',
'../../src/icu_util.h',
'../../src/ic-inl.h',
......@@ -874,19 +876,18 @@
}],
['v8_enable_i18n_support==1', {
'sources': [
'../../src/i18n.cc',
'../../src/i18n.h',
'../../src/extensions/i18n/break-iterator.cc',
'../../src/extensions/i18n/break-iterator.h',
'../../src/extensions/i18n/i18n-extension.cc',
'../../src/extensions/i18n/i18n-extension.h',
'../../src/extensions/i18n/i18n-utils.cc',
'../../src/extensions/i18n/i18n-utils.h',
],
'dependencies': [
'<(DEPTH)/third_party/icu/icu.gyp:icui18n',
'<(DEPTH)/third_party/icu/icu.gyp:icuuc',
]
}, { # v8_enable_i18n_support==0
'sources!': [
'../../src/i18n.cc',
'../../src/i18n.h',
],
}],
['OS=="win" and v8_enable_i18n_support==1', {
'dependencies': [
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment