Commit 5a92a956 authored by jochen@chromium.org's avatar jochen@chromium.org

Move i18n's number-format C++ code to runtime

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

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16099 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 63defee4
......@@ -31,7 +31,6 @@
#include "break-iterator.h"
#include "collator.h"
#include "natives.h"
#include "number-format.h"
using v8::internal::I18NNatives;
......@@ -47,15 +46,6 @@ Extension::Extension()
v8::Handle<v8::FunctionTemplate> Extension::GetNativeFunction(
v8::Handle<v8::String> name) {
// Number format and parse.
if (name->Equals(v8::String::New("NativeJSCreateNumberFormat"))) {
return v8::FunctionTemplate::New(NumberFormat::JSCreateNumberFormat);
} else if (name->Equals(v8::String::New("NativeJSInternalNumberFormat"))) {
return v8::FunctionTemplate::New(NumberFormat::JSInternalFormat);
} else if (name->Equals(v8::String::New("NativeJSInternalNumberParse"))) {
return v8::FunctionTemplate::New(NumberFormat::JSInternalParse);
}
// Collator.
if (name->Equals(v8::String::New("NativeJSCreateCollator"))) {
return v8::FunctionTemplate::New(Collator::JSCreateCollator);
......
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_NUMBER_FORMAT_H_
#define V8_EXTENSIONS_I18N_NUMBER_FORMAT_H_
#include "unicode/uversion.h"
#include "v8.h"
namespace U_ICU_NAMESPACE {
class DecimalFormat;
}
namespace v8_i18n {
class NumberFormat {
public:
static void JSCreateNumberFormat(
const v8::FunctionCallbackInfo<v8::Value>& args);
// Helper methods for various bindings.
// Unpacks date format object from corresponding JavaScript object.
static icu::DecimalFormat* UnpackNumberFormat(v8::Handle<v8::Object> obj);
// Release memory we allocated for the NumberFormat once the JS object that
// holds the pointer gets garbage collected.
static void DeleteNumberFormat(v8::Isolate* isolate,
v8::Persistent<v8::Object>* object,
void* param);
// Formats number and returns corresponding string.
static void JSInternalFormat(const v8::FunctionCallbackInfo<v8::Value>& args);
// Parses a string and returns a number.
static void JSInternalParse(const v8::FunctionCallbackInfo<v8::Value>& args);
private:
NumberFormat();
};
} // namespace v8_i18n
#endif // V8_EXTENSIONS_I18N_NUMBER_FORMAT_H_
......@@ -65,8 +65,6 @@ function getNumberOption(options, property, min, max, fallback) {
* Useful for subclassing.
*/
function initializeNumberFormat(numberFormat, locales, options) {
native function NativeJSCreateNumberFormat();
if (numberFormat.hasOwnProperty('__initializedIntlObject')) {
throw new TypeError('Trying to re-initialize NumberFormat object.');
}
......@@ -148,9 +146,9 @@ function initializeNumberFormat(numberFormat, locales, options) {
if (internalOptions.hasOwnProperty('maximumSignificantDigits')) {
defineWEProperty(resolved, 'maximumSignificantDigits', undefined);
}
var formatter = NativeJSCreateNumberFormat(requestedLocale,
internalOptions,
resolved);
var formatter = %CreateNumberFormat(requestedLocale,
internalOptions,
resolved);
// We can't get information about number or currency style from ICU, so we
// assume user request was fulfilled.
......@@ -269,15 +267,13 @@ function initializeNumberFormat(numberFormat, locales, options) {
* NumberFormat.
*/
function formatNumber(formatter, value) {
native function NativeJSInternalNumberFormat();
// Spec treats -0 and +0 as 0.
var number = Number(value);
if (number === -0) {
number = 0;
}
return NativeJSInternalNumberFormat(formatter.formatter, number);
return %InternalNumberFormat(formatter.formatter, number);
}
......@@ -285,9 +281,7 @@ function formatNumber(formatter, value) {
* Returns a Number that represents string value that was passed in.
*/
function parseNumber(formatter, value) {
native function NativeJSInternalNumberParse();
return NativeJSInternalNumberParse(formatter.formatter, String(value));
return %InternalNumberParse(formatter.formatter, String(value));
}
......
This diff is collapsed.
......@@ -33,6 +33,7 @@
#include "v8.h"
namespace U_ICU_NAMESPACE {
class DecimalFormat;
class SimpleDateFormat;
}
......@@ -51,6 +52,7 @@ class I18N {
I18N();
};
class DateFormat {
public:
// Create a formatter for the specificied locale and options. Returns the
......@@ -74,6 +76,30 @@ class DateFormat {
DateFormat();
};
class NumberFormat {
public:
// Create a formatter for the specificied locale and options. Returns the
// resolved settings for the locale / options.
static icu::DecimalFormat* InitializeNumberFormat(
Isolate* isolate,
Handle<String> locale,
Handle<JSObject> options,
Handle<JSObject> resolved);
// Unpacks number format object from corresponding JavaScript object.
static icu::DecimalFormat* UnpackNumberFormat(Isolate* isolate,
Handle<JSObject> obj);
// Release memory we allocated for the NumberFormat once the JS object that
// holds the pointer gets garbage collected.
static void DeleteNumberFormat(v8::Isolate* isolate,
Persistent<v8::Object>* object,
void* param);
private:
NumberFormat();
};
} } // namespace v8::internal
#endif // V8_I18N_H_
......@@ -71,7 +71,10 @@
#include "unicode/brkiter.h"
#include "unicode/calendar.h"
#include "unicode/coll.h"
#include "unicode/curramt.h"
#include "unicode/datefmt.h"
#include "unicode/dcfmtsym.h"
#include "unicode/decimfmt.h"
#include "unicode/dtfmtsym.h"
#include "unicode/dtptngen.h"
#include "unicode/locid.h"
......@@ -79,7 +82,10 @@
#include "unicode/numsys.h"
#include "unicode/smpdtfmt.h"
#include "unicode/timezone.h"
#include "unicode/uchar.h"
#include "unicode/ucurr.h"
#include "unicode/uloc.h"
#include "unicode/unum.h"
#include "unicode/uversion.h"
#endif
......@@ -13665,6 +13671,121 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalDateParse) {
}
return *result;
}
RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateNumberFormat) {
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> number_format_template =
I18N::GetTemplate(isolate);
// Create an empty object wrapper.
bool has_pending_exception = false;
Handle<JSObject> local_object = Execution::InstantiateObject(
number_format_template, &has_pending_exception);
if (has_pending_exception) {
ASSERT(isolate->has_pending_exception());
return Failure::Exception();
}
// Set number formatter as internal field of the resulting JS object.
icu::DecimalFormat* number_format = NumberFormat::InitializeNumberFormat(
isolate, locale, options, resolved);
if (!number_format) return isolate->ThrowIllegalOperation();
local_object->SetInternalField(0, reinterpret_cast<Smi*>(number_format));
RETURN_IF_EMPTY_HANDLE(isolate,
JSObject::SetLocalPropertyIgnoreAttributes(
local_object,
isolate->factory()->NewStringFromAscii(CStrVector("numberFormat")),
isolate->factory()->NewStringFromAscii(CStrVector("valid")),
NONE));
Persistent<v8::Object> wrapper(reinterpret_cast<v8::Isolate*>(isolate),
v8::Utils::ToLocal(local_object));
// Make object handle weak so we can delete the number format once GC kicks
// in.
wrapper.MakeWeak<void>(NULL, &NumberFormat::DeleteNumberFormat);
Handle<Object> result = Utils::OpenPersistent(wrapper);
wrapper.ClearAndLeak();
return *result;
}
RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalNumberFormat) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSObject, number_format_holder, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, number, 1);
bool has_pending_exception = false;
double value = Execution::ToNumber(number, &has_pending_exception)->Number();
if (has_pending_exception) {
ASSERT(isolate->has_pending_exception());
return Failure::Exception();
}
icu::DecimalFormat* number_format =
NumberFormat::UnpackNumberFormat(isolate, number_format_holder);
if (!number_format) return isolate->ThrowIllegalOperation();
icu::UnicodeString result;
number_format->format(value, result);
return *isolate->factory()->NewStringFromTwoByte(
Vector<const uint16_t>(
reinterpret_cast<const uint16_t*>(result.getBuffer()),
result.length()));
}
RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalNumberParse) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSObject, number_format_holder, 0);
CONVERT_ARG_HANDLE_CHECKED(String, number_string, 1);
v8::String::Utf8Value utf8_number(v8::Utils::ToLocal(number_string));
icu::UnicodeString u_number(icu::UnicodeString::fromUTF8(*utf8_number));
icu::DecimalFormat* number_format =
NumberFormat::UnpackNumberFormat(isolate, number_format_holder);
if (!number_format) return isolate->ThrowIllegalOperation();
UErrorCode status = U_ZERO_ERROR;
icu::Formattable result;
// ICU 4.6 doesn't support parseCurrency call. We need to wait for ICU49
// to be part of Chrome.
// TODO(cira): Include currency parsing code using parseCurrency call.
// We need to check if the formatter parses all currencies or only the
// one it was constructed with (it will impact the API - how to return ISO
// code and the value).
number_format->parse(u_number, result, status);
if (U_FAILURE(status)) return isolate->heap()->undefined_value();
switch (result.getType()) {
case icu::Formattable::kDouble:
return *isolate->factory()->NewNumber(result.getDouble());
case icu::Formattable::kLong:
return *isolate->factory()->NewNumberFromInt(result.getLong());
case icu::Formattable::kInt64:
return *isolate->factory()->NewNumber(
static_cast<double>(result.getInt64()));
default:
return isolate->heap()->undefined_value();
}
}
#endif // V8_I18N_SUPPORT
......
......@@ -548,6 +548,11 @@ namespace internal {
F(CreateDateTimeFormat, 3, 1) \
F(InternalDateFormat, 2, 1) \
F(InternalDateParse, 2, 1) \
\
/* Number format and parse. */ \
F(CreateNumberFormat, 3, 1) \
F(InternalNumberFormat, 2, 1) \
F(InternalNumberParse, 2, 1) \
#else
#define RUNTIME_FUNCTION_LIST_I18N_SUPPORT(F)
......
......@@ -833,8 +833,6 @@
'../../src/extensions/i18n/i18n-extension.h',
'../../src/extensions/i18n/i18n-utils.cc',
'../../src/extensions/i18n/i18n-utils.h',
'../../src/extensions/i18n/number-format.cc',
'../../src/extensions/i18n/number-format.h',
],
'dependencies': [
'<(DEPTH)/third_party/icu/icu.gyp:icui18n',
......
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