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 |