| Index: src/runtime.cc
|
| diff --git a/src/runtime.cc b/src/runtime.cc
|
| index 0916b9398950ac5d4285b2652b7af461cce2cd5a..e08eabbf6a47aba987415d648945cd306776722f 100644
|
| --- a/src/runtime.cc
|
| +++ b/src/runtime.cc
|
| @@ -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
|
|
|
|
|
|
|