Chromium Code Reviews| Index: src/runtime/runtime-i18n.cc |
| diff --git a/src/runtime/runtime-i18n.cc b/src/runtime/runtime-i18n.cc |
| index 8b9d92ec006eb570bf14755087d97987b8d04e2d..be5a02a4bad3058cbc4303305440ffa293c7b6d1 100644 |
| --- a/src/runtime/runtime-i18n.cc |
| +++ b/src/runtime/runtime-i18n.cc |
| @@ -25,6 +25,8 @@ |
| #include "unicode/decimfmt.h" |
| #include "unicode/dtfmtsym.h" |
| #include "unicode/dtptngen.h" |
| +#include "unicode/fieldpos.h" |
| +#include "unicode/fpositer.h" |
| #include "unicode/locid.h" |
| #include "unicode/normalizer2.h" |
| #include "unicode/numfmt.h" |
| @@ -393,6 +395,132 @@ RUNTIME_FUNCTION(Runtime_InternalDateFormat) { |
| result.length()))); |
| } |
| +namespace { |
| +// The list comes from third_party/icu/source/i18n/unicode/udat.h. |
| +// They're mapped to DateTimeFormat components listed at |
| +// https://tc39.github.io/ecma402/#sec-datetimeformat-abstracts . |
| + |
| +Handle<String> IcuDateFieldIdToDateType(int32_t field_id, Isolate* isolate) { |
| + switch (field_id) { |
| + case -1: |
| + return isolate->factory()->literal_string(); |
| + case UDAT_YEAR_FIELD: |
| + case UDAT_EXTENDED_YEAR_FIELD: |
| + case UDAT_YEAR_NAME_FIELD: |
| + return isolate->factory()->year_string(); |
| + case UDAT_MONTH_FIELD: |
| + case UDAT_STANDALONE_MONTH_FIELD: |
| + return isolate->factory()->month_string(); |
| + case UDAT_DATE_FIELD: |
| + return isolate->factory()->day_string(); |
| + case UDAT_HOUR_OF_DAY1_FIELD: |
| + case UDAT_HOUR_OF_DAY0_FIELD: |
| + case UDAT_HOUR1_FIELD: |
| + case UDAT_HOUR0_FIELD: |
| + return isolate->factory()->hour_string(); |
| + case UDAT_MINUTE_FIELD: |
| + return isolate->factory()->minute_string(); |
| + case UDAT_SECOND_FIELD: |
| + return isolate->factory()->second_string(); |
| + case UDAT_DAY_OF_WEEK_FIELD: |
| + case UDAT_DOW_LOCAL_FIELD: |
| + case UDAT_STANDALONE_DAY_FIELD: |
| + return isolate->factory()->weekday_string(); |
| + case UDAT_AM_PM_FIELD: |
| + return isolate->factory()->dayperiod_string(); |
| + case UDAT_TIMEZONE_FIELD: |
| + case UDAT_TIMEZONE_RFC_FIELD: |
| + case UDAT_TIMEZONE_GENERIC_FIELD: |
| + case UDAT_TIMEZONE_SPECIAL_FIELD: |
| + case UDAT_TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD: |
| + case UDAT_TIMEZONE_ISO_FIELD: |
| + case UDAT_TIMEZONE_ISO_LOCAL_FIELD: |
| + return isolate->factory()->timeZoneName_string(); |
| + case UDAT_ERA_FIELD: |
| + return isolate->factory()->era_string(); |
| + default: |
|
Dan Ehrenberg
2016/08/26 19:07:10
Could you add a comment explaining why this is UNR
|
| + UNREACHABLE(); |
| + } |
| +} |
| + |
| +bool AddElement(Handle<JSArray> array, int index, int32_t field_id, |
| + const icu::UnicodeString& formatted, int32_t begin, int32_t end, |
| + Isolate* isolate) { |
| + HandleScope scope(isolate); |
| + Factory* factory = isolate->factory(); |
| + Handle<JSObject> element = factory->NewJSObject(isolate->object_function()); |
| + Handle<String> value = IcuDateFieldIdToDateType(field_id, isolate); |
| + JSObject::AddProperty(element, factory->type_string(), value, NONE); |
| + |
| + icu::UnicodeString field(formatted.tempSubStringBetween(begin, end)); |
| + ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| + isolate, value, factory->NewStringFromTwoByte(Vector<const uint16_t>( |
| + reinterpret_cast<const uint16_t*>(field.getBuffer()), |
| + field.length())), |
| + false); |
| + |
| + JSObject::AddProperty(element, factory->value_string(), value, NONE); |
| + RETURN_ON_EXCEPTION_VALUE( |
| + isolate, JSObject::AddDataElement(array, index, element, NONE), false); |
| + return true; |
| +} |
| + |
| +} // namespace |
| + |
| +RUNTIME_FUNCTION(Runtime_InternalDateFormatToParts) { |
| + HandleScope scope(isolate); |
| + Factory* factory = isolate->factory(); |
| + |
| + DCHECK(args.length() == 2); |
| + |
| + CONVERT_ARG_HANDLE_CHECKED(JSObject, date_format_holder, 0); |
| + CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 1); |
| + |
| + Handle<Object> value; |
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(date)); |
| + |
| + icu::SimpleDateFormat* date_format = |
| + DateFormat::UnpackDateFormat(isolate, date_format_holder); |
| + if (!date_format) return isolate->ThrowIllegalOperation(); |
| + |
| + icu::UnicodeString formatted; |
| + icu::FieldPositionIterator fp_iter; |
| + icu::FieldPosition fp; |
| + UErrorCode status = U_ZERO_ERROR; |
| + date_format->format(value->Number(), formatted, &fp_iter, status); |
| + if (U_FAILURE(status)) return isolate->heap()->undefined_value(); |
| + |
| + Handle<JSArray> result = factory->NewJSArray(0); |
| + int index = 0; |
| + int32_t previous_end_pos = 0; |
| + while (fp_iter.next(fp)) { |
| + int32_t begin_pos = fp.getBeginIndex(); |
| + int32_t end_pos = fp.getEndIndex(); |
| + |
| + if (previous_end_pos < begin_pos) { |
| + if (!AddElement(result, index, -1, formatted, previous_end_pos, begin_pos, |
| + isolate)) { |
| + return isolate->heap()->undefined_value(); |
| + } |
| + ++index; |
| + } |
| + if (!AddElement(result, index, fp.getField(), formatted, begin_pos, end_pos, |
| + isolate)) { |
| + return isolate->heap()->undefined_value(); |
| + } |
| + previous_end_pos = end_pos; |
| + ++index; |
| + } |
| + int32_t length = formatted.length(); |
| + if (previous_end_pos < length) { |
| + if (!AddElement(result, index, -1, formatted, previous_end_pos, length, |
| + isolate)) { |
| + return isolate->heap()->undefined_value(); |
| + } |
| + } |
| + JSObject::ValidateElements(result); |
| + return *result; |
| +} |
| RUNTIME_FUNCTION(Runtime_InternalDateParse) { |
| HandleScope scope(isolate); |