Add support for DateTimeFormat.formatToParts
Spec discussion: https://github.com/tc39/ecma402/issues/30 It's in stage 4 and Firefox has already implemented it. For now, it's added to HARMONY_IN_PROGRESS bucket behind '--datetime-format-to-parts' flag. BUG=v8:5244 TEST=intl/date-format/date-format-to-parts.js TEST=test262/intl402/DateTimeFormat/prototype/formatToParts/* Review-Url: https://codereview.chromium.org/2273953003 Cr-Commit-Position: refs/heads/master@{#39225}
This commit is contained in:
parent
01cc19fa6f
commit
a3db819c9e
1
BUILD.gn
1
BUILD.gn
@ -439,6 +439,7 @@ action("js2c_experimental") {
|
||||
|
||||
if (v8_enable_i18n_support) {
|
||||
sources += [
|
||||
"src/js/datetime-format-to-parts.js",
|
||||
"src/js/icu-case-mapping.js",
|
||||
"src/js/intl-extra.js",
|
||||
]
|
||||
|
@ -210,7 +210,9 @@ class Genesis BASE_EMBEDDED {
|
||||
HARMONY_INPROGRESS(DECLARE_FEATURE_INITIALIZATION)
|
||||
HARMONY_STAGED(DECLARE_FEATURE_INITIALIZATION)
|
||||
HARMONY_SHIPPING(DECLARE_FEATURE_INITIALIZATION)
|
||||
#ifdef V8_I18N_SUPPORT
|
||||
DECLARE_FEATURE_INITIALIZATION(intl_extra, "")
|
||||
#endif
|
||||
#undef DECLARE_FEATURE_INITIALIZATION
|
||||
|
||||
Handle<JSFunction> InstallArrayBuffer(Handle<JSObject> target,
|
||||
@ -2209,7 +2211,9 @@ void Genesis::InitializeExperimentalGlobal() {
|
||||
HARMONY_INPROGRESS(FEATURE_INITIALIZE_GLOBAL)
|
||||
HARMONY_STAGED(FEATURE_INITIALIZE_GLOBAL)
|
||||
HARMONY_SHIPPING(FEATURE_INITIALIZE_GLOBAL)
|
||||
#ifdef V8_I18N_SUPPORT
|
||||
FEATURE_INITIALIZE_GLOBAL(intl_extra, "")
|
||||
#endif
|
||||
#undef FEATURE_INITIALIZE_GLOBAL
|
||||
}
|
||||
|
||||
@ -2771,6 +2775,7 @@ void Bootstrapper::ExportExperimentalFromRuntime(Isolate* isolate,
|
||||
Handle<JSObject> container) {
|
||||
HandleScope scope(isolate);
|
||||
|
||||
#ifdef V8_I18N_SUPPORT
|
||||
#define INITIALIZE_FLAG(FLAG) \
|
||||
{ \
|
||||
Handle<String> name = \
|
||||
@ -2782,6 +2787,7 @@ void Bootstrapper::ExportExperimentalFromRuntime(Isolate* isolate,
|
||||
INITIALIZE_FLAG(FLAG_intl_extra)
|
||||
|
||||
#undef INITIALIZE_FLAG
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -2794,13 +2800,14 @@ EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_regexp_lookbehind)
|
||||
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_regexp_named_captures)
|
||||
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_regexp_property)
|
||||
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_function_sent)
|
||||
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(intl_extra)
|
||||
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_explicit_tailcalls)
|
||||
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_tailcalls)
|
||||
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_restrictive_declarations)
|
||||
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_string_padding)
|
||||
#ifdef V8_I18N_SUPPORT
|
||||
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(datetime_format_to_parts)
|
||||
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(icu_case_mapping)
|
||||
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(intl_extra)
|
||||
#endif
|
||||
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_async_await)
|
||||
EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_restrictive_generators)
|
||||
@ -3381,7 +3388,6 @@ bool Genesis::InstallExperimentalNatives() {
|
||||
static const char* harmony_regexp_named_captures_natives[] = {nullptr};
|
||||
static const char* harmony_regexp_property_natives[] = {nullptr};
|
||||
static const char* harmony_function_sent_natives[] = {nullptr};
|
||||
static const char* intl_extra_natives[] = {"native intl-extra.js", nullptr};
|
||||
static const char* harmony_object_values_entries_natives[] = {nullptr};
|
||||
static const char* harmony_object_own_property_descriptors_natives[] = {
|
||||
nullptr};
|
||||
@ -3391,6 +3397,9 @@ bool Genesis::InstallExperimentalNatives() {
|
||||
#ifdef V8_I18N_SUPPORT
|
||||
static const char* icu_case_mapping_natives[] = {"native icu-case-mapping.js",
|
||||
nullptr};
|
||||
static const char* intl_extra_natives[] = {"native intl-extra.js", nullptr};
|
||||
static const char* datetime_format_to_parts_natives[] = {
|
||||
"native datetime-format-to-parts.js", nullptr};
|
||||
#endif
|
||||
static const char* harmony_async_await_natives[] = {
|
||||
"native harmony-async-await.js", nullptr};
|
||||
@ -3414,7 +3423,9 @@ bool Genesis::InstallExperimentalNatives() {
|
||||
HARMONY_INPROGRESS(INSTALL_EXPERIMENTAL_NATIVES);
|
||||
HARMONY_STAGED(INSTALL_EXPERIMENTAL_NATIVES);
|
||||
HARMONY_SHIPPING(INSTALL_EXPERIMENTAL_NATIVES);
|
||||
#ifdef V8_I18N_SUPPORT
|
||||
INSTALL_EXPERIMENTAL_NATIVES(intl_extra, "");
|
||||
#endif
|
||||
#undef INSTALL_EXPERIMENTAL_NATIVES
|
||||
}
|
||||
|
||||
|
@ -180,16 +180,18 @@ DEFINE_BOOL(harmony, false, "enable all completed harmony features")
|
||||
DEFINE_BOOL(harmony_shipping, true, "enable all shipped harmony features")
|
||||
DEFINE_IMPLICATION(es_staging, harmony)
|
||||
|
||||
#ifdef V8_I18N_SUPPORT
|
||||
DEFINE_BOOL(intl_extra, false, "additional V8 Intl functions")
|
||||
// Removing extra Intl functions is shipped
|
||||
DEFINE_NEG_VALUE_IMPLICATION(harmony_shipping, intl_extra, true)
|
||||
#endif
|
||||
|
||||
// Activate on ClusterFuzz.
|
||||
DEFINE_IMPLICATION(es_staging, harmony_regexp_lookbehind)
|
||||
DEFINE_IMPLICATION(es_staging, move_object_start)
|
||||
|
||||
// Features that are still work in progress (behind individual flags).
|
||||
#define HARMONY_INPROGRESS(V) \
|
||||
#define HARMONY_INPROGRESS_BASE(V) \
|
||||
V(harmony_array_prototype_values, "harmony Array.prototype.values") \
|
||||
V(harmony_function_sent, "harmony function.sent") \
|
||||
V(harmony_sharedarraybuffer, "harmony sharedarraybuffer") \
|
||||
@ -204,6 +206,14 @@ DEFINE_IMPLICATION(es_staging, move_object_start)
|
||||
V(harmony_trailing_commas, \
|
||||
"harmony trailing commas in function parameter lists")
|
||||
|
||||
#ifdef V8_I18N_SUPPORT
|
||||
#define HARMONY_INPROGRESS(V) \
|
||||
HARMONY_INPROGRESS_BASE(V) \
|
||||
V(datetime_format_to_parts, "Intl.DateTimeFormat.formatToParts")
|
||||
#else
|
||||
#define HARMONY_INPROGRESS(V) HARMONY_INPROGRESS_BASE(V)
|
||||
#endif
|
||||
|
||||
// Features that are complete (but still behind --harmony/es-staging flag).
|
||||
#define HARMONY_STAGED_BASE(V) \
|
||||
V(harmony_regexp_lookbehind, "harmony regexp lookbehind") \
|
||||
|
@ -8,11 +8,11 @@
|
||||
#define INTERNALIZED_STRING_LIST(V) \
|
||||
V(anonymous_string, "anonymous") \
|
||||
V(apply_string, "apply") \
|
||||
V(assign_string, "assign") \
|
||||
V(arguments_string, "arguments") \
|
||||
V(Arguments_string, "Arguments") \
|
||||
V(Array_string, "Array") \
|
||||
V(arguments_to_string, "[object Arguments]") \
|
||||
V(Array_string, "Array") \
|
||||
V(assign_string, "assign") \
|
||||
V(array_to_string, "[object Array]") \
|
||||
V(boolean_to_string, "[object Boolean]") \
|
||||
V(date_to_string, "[object Date]") \
|
||||
@ -48,6 +48,8 @@
|
||||
V(construct_string, "construct") \
|
||||
V(create_string, "create") \
|
||||
V(Date_string, "Date") \
|
||||
V(dayperiod_string, "dayperiod") \
|
||||
V(day_string, "day") \
|
||||
V(default_string, "default") \
|
||||
V(defineProperty_string, "defineProperty") \
|
||||
V(deleteProperty_string, "deleteProperty") \
|
||||
@ -57,6 +59,7 @@
|
||||
V(dot_string, ".") \
|
||||
V(entries_string, "entries") \
|
||||
V(enumerable_string, "enumerable") \
|
||||
V(era_string, "era") \
|
||||
V(Error_string, "Error") \
|
||||
V(eval_string, "eval") \
|
||||
V(EvalError_string, "EvalError") \
|
||||
@ -74,6 +77,8 @@
|
||||
V(get_string, "get") \
|
||||
V(global_string, "global") \
|
||||
V(has_string, "has") \
|
||||
V(hour_string, "hour") \
|
||||
V(ignoreCase_string, "ignoreCase") \
|
||||
V(illegal_access_string, "illegal access") \
|
||||
V(illegal_argument_string, "illegal argument") \
|
||||
V(index_string, "index") \
|
||||
@ -92,10 +97,14 @@
|
||||
V(last_index_string, "lastIndex") \
|
||||
V(length_string, "length") \
|
||||
V(line_string, "line") \
|
||||
V(literal_string, "literal") \
|
||||
V(Map_string, "Map") \
|
||||
V(message_string, "message") \
|
||||
V(minus_infinity_string, "-Infinity") \
|
||||
V(minus_zero_string, "-0") \
|
||||
V(minute_string, "minute") \
|
||||
V(month_string, "month") \
|
||||
V(multiline_string, "multiline") \
|
||||
V(name_string, "name") \
|
||||
V(nan_string, "NaN") \
|
||||
V(next_string, "next") \
|
||||
@ -120,6 +129,7 @@
|
||||
V(ReferenceError_string, "ReferenceError") \
|
||||
V(RegExp_string, "RegExp") \
|
||||
V(script_string, "script") \
|
||||
V(second_string, "second") \
|
||||
V(setPrototypeOf_string, "setPrototypeOf") \
|
||||
V(set_string, "set") \
|
||||
V(Set_string, "Set") \
|
||||
@ -138,10 +148,12 @@
|
||||
V(this_string, "this") \
|
||||
V(throw_string, "throw") \
|
||||
V(timed_out, "timed-out") \
|
||||
V(timeZoneName_string, "timeZoneName") \
|
||||
V(toJSON_string, "toJSON") \
|
||||
V(toString_string, "toString") \
|
||||
V(true_string, "true") \
|
||||
V(TypeError_string, "TypeError") \
|
||||
V(type_string, "type") \
|
||||
V(uint16x8_string, "uint16x8") \
|
||||
V(Uint16x8_string, "Uint16x8") \
|
||||
V(uint32x4_string, "uint32x4") \
|
||||
@ -156,7 +168,9 @@
|
||||
V(value_string, "value") \
|
||||
V(WeakMap_string, "WeakMap") \
|
||||
V(WeakSet_string, "WeakSet") \
|
||||
V(writable_string, "writable")
|
||||
V(weekday_string, "weekday") \
|
||||
V(writable_string, "writable") \
|
||||
V(year_string, "year")
|
||||
|
||||
#define PRIVATE_SYMBOL_LIST(V) \
|
||||
V(array_iteration_kind_symbol) \
|
||||
|
12
src/i18n.cc
12
src/i18n.cc
@ -5,6 +5,8 @@
|
||||
|
||||
#include "src/i18n.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "src/api.h"
|
||||
#include "src/factory.h"
|
||||
#include "src/isolate.h"
|
||||
@ -115,13 +117,11 @@ icu::SimpleDateFormat* CreateICUDateFormat(
|
||||
icu::SimpleDateFormat* date_format = NULL;
|
||||
icu::UnicodeString skeleton;
|
||||
if (ExtractStringSetting(isolate, options, "skeleton", &skeleton)) {
|
||||
icu::DateTimePatternGenerator* generator =
|
||||
icu::DateTimePatternGenerator::createInstance(icu_locale, status);
|
||||
std::unique_ptr<icu::DateTimePatternGenerator> generator(
|
||||
icu::DateTimePatternGenerator::createInstance(icu_locale, status));
|
||||
icu::UnicodeString pattern;
|
||||
if (U_SUCCESS(status)) {
|
||||
if (U_SUCCESS(status))
|
||||
pattern = generator->getBestPattern(skeleton, status);
|
||||
delete generator;
|
||||
}
|
||||
|
||||
date_format = new icu::SimpleDateFormat(pattern, icu_locale, status);
|
||||
if (U_SUCCESS(status)) {
|
||||
@ -132,7 +132,7 @@ icu::SimpleDateFormat* CreateICUDateFormat(
|
||||
if (U_FAILURE(status)) {
|
||||
delete calendar;
|
||||
delete date_format;
|
||||
date_format = NULL;
|
||||
date_format = nullptr;
|
||||
}
|
||||
|
||||
return date_format;
|
||||
|
16
src/js/datetime-format-to-parts.js
Normal file
16
src/js/datetime-format-to-parts.js
Normal file
@ -0,0 +1,16 @@
|
||||
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
(function(global, utils) {
|
||||
"use strict";
|
||||
|
||||
%CheckIsBootstrapping();
|
||||
|
||||
var GlobalIntl = global.Intl;
|
||||
var FormatDateToParts = utils.ImportNow("FormatDateToParts");
|
||||
|
||||
utils.InstallFunctions(GlobalIntl.DateTimeFormat.prototype, DONT_ENUM, [
|
||||
'formatToParts', FormatDateToParts
|
||||
]);
|
||||
})
|
@ -1797,6 +1797,29 @@ function formatDate(formatter, dateValue) {
|
||||
new GlobalDate(dateMs));
|
||||
}
|
||||
|
||||
function FormatDateToParts(dateValue) {
|
||||
if (!IS_UNDEFINED(new.target)) {
|
||||
throw %make_type_error(kOrdinaryFunctionCalledAsConstructor);
|
||||
}
|
||||
CHECK_OBJECT_COERCIBLE(this, "Intl.DateTimeFormat.prototype.formatToParts");
|
||||
if (!IS_OBJECT(this)) {
|
||||
throw %make_type_error(kCalledOnNonObject, this);
|
||||
}
|
||||
var dateMs;
|
||||
if (IS_UNDEFINED(dateValue)) {
|
||||
dateMs = %DateCurrentTime();
|
||||
} else {
|
||||
dateMs = TO_NUMBER(dateValue);
|
||||
}
|
||||
|
||||
if (!NUMBER_IS_FINITE(dateMs)) throw %make_range_error(kDateRange);
|
||||
|
||||
return %InternalDateFormatToParts(
|
||||
%GetImplFromInitializedIntlObject(this), new GlobalDate(dateMs));
|
||||
}
|
||||
|
||||
%FunctionSetLength(FormatDateToParts, 0);
|
||||
|
||||
|
||||
/**
|
||||
* Returns a Date object representing the result of calling ToString(value)
|
||||
@ -2291,8 +2314,11 @@ OverrideFunction(GlobalDate.prototype, 'toLocaleTimeString', function() {
|
||||
}
|
||||
);
|
||||
|
||||
%FunctionRemovePrototype(FormatDateToParts);
|
||||
|
||||
utils.Export(function(to) {
|
||||
to.AddBoundMethod = AddBoundMethod;
|
||||
to.FormatDateToParts = FormatDateToParts;
|
||||
to.IntlParseDate = IntlParseDate;
|
||||
to.IntlParseNumber = IntlParseNumber;
|
||||
});
|
||||
|
@ -185,6 +185,7 @@ function PostNatives(utils) {
|
||||
"ArrayToString",
|
||||
"AsyncFunctionNext",
|
||||
"AsyncFunctionThrow",
|
||||
"FormatDateToParts",
|
||||
"GetIterator",
|
||||
"GetMethod",
|
||||
"GlobalPromise",
|
||||
|
@ -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"
|
||||
@ -322,7 +324,7 @@ RUNTIME_FUNCTION(Runtime_GetImplFromInitializedIntlObject) {
|
||||
Handle<Symbol> marker = isolate->factory()->intl_impl_object_symbol();
|
||||
|
||||
Handle<Object> impl = JSReceiver::GetDataProperty(obj, marker);
|
||||
if (impl->IsTheHole(isolate)) {
|
||||
if (!impl->IsJSObject()) {
|
||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
isolate, NewTypeError(MessageTemplate::kNotIntlObject, obj));
|
||||
}
|
||||
@ -393,6 +395,138 @@ 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:
|
||||
// Other UDAT_*_FIELD's cannot show up because there is no way to specify
|
||||
// them via options of Intl.DateTimeFormat.
|
||||
UNREACHABLE();
|
||||
// To prevent MSVC from issuing C4715 warning.
|
||||
return Handle<String>();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
int32_t length = formatted.length();
|
||||
if (length == 0) return *result;
|
||||
|
||||
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;
|
||||
}
|
||||
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);
|
||||
|
@ -260,6 +260,7 @@ namespace internal {
|
||||
F(GetImplFromInitializedIntlObject, 1, 1) \
|
||||
F(CreateDateTimeFormat, 3, 1) \
|
||||
F(InternalDateFormat, 2, 1) \
|
||||
F(InternalDateFormatToParts, 2, 1) \
|
||||
F(InternalDateParse, 2, 1) \
|
||||
F(CreateNumberFormat, 3, 1) \
|
||||
F(InternalNumberFormat, 2, 1) \
|
||||
|
@ -2213,6 +2213,7 @@
|
||||
['v8_enable_i18n_support==1', {
|
||||
'library_files': ['js/i18n.js'],
|
||||
'experimental_library_files': [
|
||||
'js/datetime-format-to-parts.js',
|
||||
'js/icu-case-mapping.js',
|
||||
'js/intl-extra.js',
|
||||
],
|
||||
|
@ -27,6 +27,14 @@
|
||||
|
||||
// Some methods are taken from v8/test/mjsunit/mjsunit.js
|
||||
|
||||
|
||||
function classOf(object) {
|
||||
// Argument must not be null or undefined.
|
||||
var string = Object.prototype.toString.call(object);
|
||||
// String has format [object <ClassName>].
|
||||
return string.substring(8, string.length - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two objects for key/value equality.
|
||||
* Returns true if they are equal, false otherwise.
|
||||
|
20
test/intl/date-format/date-format-to-parts.js
Normal file
20
test/intl/date-format/date-format-to-parts.js
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --datetime-format-to-parts
|
||||
|
||||
var d = new Date(2016, 11, 15, 14, 10, 34);
|
||||
var df = Intl.DateTimeFormat("ja",
|
||||
{hour: 'numeric', minute: 'numeric', second: 'numeric', year: 'numeric',
|
||||
month: 'numeric', day: 'numeric', timeZoneName: 'short', era: 'short'});
|
||||
|
||||
var formattedParts = df.formatToParts(d);
|
||||
|
||||
var formattedReconstructedFromParts = formattedParts.map((part) => part.value)
|
||||
.reduce((accumulated, part) => accumulated + part);
|
||||
assertEquals(df.format(d), formattedReconstructedFromParts);
|
||||
// 西暦2016年11月15日 14:10:34 GMT-7
|
||||
assertEquals(["era", "year", "literal", "month", "literal", "day", "literal",
|
||||
"hour", "literal", "minute", "literal", "second", "literal",
|
||||
"timeZoneName"], formattedParts.map((part) => part.type));
|
Loading…
Reference in New Issue
Block a user