Revert "[Intl] Move ToDateTimeOptions/ToLocaleDateTime to C++"

This reverts commit cabcfb3a5d.

Reason for revert: Breaks a layout test "fast/js/date-proto-generic-invocation.html" as can be seen in 
https://ci.chromium.org/p/v8/builders/luci.v8.ci/V8-Blink%20Linux%2064/25626

Original change's description:
> [Intl] Move ToDateTimeOptions/ToLocaleDateTime to C++
> 
> Bug: v8:7961
> Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng
> Change-Id: Ic414a51a64040f253da1d7ccf03c558ea70ad2bf
> Reviewed-on: https://chromium-review.googlesource.com/1155271
> Commit-Queue: Frank Tang <ftang@chromium.org>
> Reviewed-by: Sathya Gunasekaran <gsathya@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#55199}

TBR=kadams@nvidia.com,jshin@chromium.org,gsathya@chromium.org,ftang@chromium.org

# Not skipping CQ checks because original CL landed > 1 day ago.

Bug: v8:7961
Change-Id: I39203fb281b9a54236b12a69c1f8389bcb5d411f
Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng
Reviewed-on: https://chromium-review.googlesource.com/1183165
Reviewed-by: Sigurd Schneider <sigurds@chromium.org>
Reviewed-by: Maya Lekova <mslekova@chromium.org>
Commit-Queue: Maya Lekova <mslekova@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55259}
This commit is contained in:
Sigurd Schneider 2018-08-21 12:10:00 +02:00 committed by Commit Bot
parent fcfd995aa1
commit 41b3955fbf
8 changed files with 70 additions and 247 deletions

View File

@ -1102,7 +1102,7 @@ function CreateDateTimeFormat(locales, options) {
var locale = resolveLocale('dateformat', locales, options);
options = %ToDateTimeOptions(options, 'any', 'date');
options = toDateTimeOptions(options, 'any', 'date');
var getOption = getGetOption(options, 'dateformat');
@ -1510,6 +1510,26 @@ function cachedOrNewService(service, locales, options, defaults) {
"cached_or_new_service", cachedOrNewService
]);
/**
* Returns actual formatted date or fails if date parameter is invalid.
*/
function toLocaleDateTime(date, locales, options, required, defaults, service) {
if (!(date instanceof GlobalDate)) {
throw %make_type_error(kMethodInvokedOnWrongType, "Date");
}
var dateValue = TO_NUMBER(date);
if (NUMBER_IS_NAN(dateValue)) return 'Invalid Date';
var internalOptions = toDateTimeOptions(options, required, defaults);
var dateFormat =
cachedOrNewService(service, locales, options, internalOptions);
return %FormatDate(dateFormat, date);
}
/**
* Formats a Date object (this) using locale and options values.
* If locale or options are omitted, defaults are used - both date and time are
@ -1520,7 +1540,7 @@ DEFINE_METHOD(
toLocaleString() {
var locales = arguments[0];
var options = arguments[1];
return %ToLocaleDateTime(
return toLocaleDateTime(
this, locales, options, 'any', 'all', 'dateformatall');
}
);
@ -1536,7 +1556,7 @@ DEFINE_METHOD(
toLocaleDateString() {
var locales = arguments[0];
var options = arguments[1];
return %ToLocaleDateTime(
return toLocaleDateTime(
this, locales, options, 'date', 'date', 'dateformatdate');
}
);
@ -1552,7 +1572,7 @@ DEFINE_METHOD(
toLocaleTimeString() {
var locales = arguments[0];
var options = arguments[1];
return %ToLocaleDateTime(
return toLocaleDateTime(
this, locales, options, 'time', 'time', 'dateformattime');
}
);

View File

@ -1342,27 +1342,6 @@ MaybeHandle<JSObject> JSObject::New(Handle<JSFunction> constructor,
return result;
}
// 9.1.12 ObjectCreate ( proto [ , internalSlotsList ] )
// Notice: This is NOT 19.1.2.2 Object.create ( O, Properties )
MaybeHandle<JSObject> JSObject::ObjectCreate(Isolate* isolate,
Handle<Object> prototype) {
// Generate the map with the specified {prototype} based on the Object
// function's initial map from the current native context.
// TODO(bmeurer): Use a dedicated cache for Object.create; think about
// slack tracking for Object.create.
Handle<Map> map =
Map::GetObjectCreateMap(isolate, Handle<HeapObject>::cast(prototype));
// Actually allocate the object.
Handle<JSObject> object;
if (map->is_dictionary_map()) {
object = isolate->factory()->NewSlowJSObjectFromMap(map);
} else {
object = isolate->factory()->NewJSObjectFromMap(map);
}
return object;
}
void JSObject::EnsureWritableFastElements(Handle<JSObject> object) {
DCHECK(object->HasSmiOrObjectElements() ||
object->HasFastStringWrapperElements());

View File

@ -2235,11 +2235,6 @@ class JSObject: public JSReceiver {
static MaybeHandle<Context> GetFunctionRealm(Handle<JSObject> object);
// 9.1.12 ObjectCreate ( proto [ , internalSlotsList ] )
// Notice: This is NOT 19.1.2.2 Object.create ( O, Properties )
static V8_WARN_UNUSED_RESULT MaybeHandle<JSObject> ObjectCreate(
Isolate* isolate, Handle<Object> prototype);
// [elements]: The elements (properties with names that are integers).
//
// Elements can be in two general modes: fast and slow. Each mode

View File

@ -552,23 +552,6 @@ void SetResolvedBreakIteratorSettings(Isolate* isolate,
.Assert();
}
}
MaybeHandle<JSObject> CachedOrNewService(Isolate* isolate,
Handle<String> service,
Handle<Object> locales,
Handle<Object> options,
Handle<Object> internal_options) {
Handle<Object> result;
Handle<Object> undefined_value(ReadOnlyRoots(isolate).undefined_value(),
isolate);
Handle<Object> args[] = {service, locales, options, internal_options};
ASSIGN_RETURN_ON_EXCEPTION(
isolate, result,
Execution::Call(isolate, isolate->cached_or_new_service(),
undefined_value, arraysize(args), args),
JSArray);
return Handle<JSObject>::cast(result);
}
} // namespace
icu::Locale Intl::CreateICULocale(Isolate* isolate,
@ -705,44 +688,6 @@ MaybeHandle<String> DateFormat::DateTimeFormat(
return DateFormat::FormatDateTime(isolate, date_time_format_holder, x);
}
MaybeHandle<String> DateFormat::ToLocaleDateTime(
Isolate* isolate, Handle<Object> date, Handle<Object> locales,
Handle<Object> options, const char* required, const char* defaults,
const char* service) {
Factory* factory = isolate->factory();
// 1. Let x be ? thisTimeValue(this value);
if (!date->IsJSDate()) {
THROW_NEW_ERROR(isolate,
NewTypeError(MessageTemplate::kMethodInvokedOnWrongType,
factory->NewStringFromStaticChars("date")),
String);
}
double const x = Handle<JSDate>::cast(date)->value()->Number();
// 2. If x is NaN, return "Invalid Date"
if (std::isnan(x)) {
return factory->NewStringFromStaticChars("Invalid Date");
}
// 3. Let options be ? ToDateTimeOptions(options, required, defaults).
Handle<JSObject> internal_options;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, internal_options,
DateFormat::ToDateTimeOptions(isolate, options, required, defaults),
String);
// 4. Let dateFormat be ? Construct(%DateTimeFormat%, « locales, options »).
Handle<JSObject> date_format;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, date_format,
CachedOrNewService(isolate, factory->NewStringFromAsciiChecked(service),
locales, options, internal_options),
String);
// 5. Return FormatDateTime(dateFormat, x).
return DateFormat::FormatDateTime(isolate, date_format, x);
}
icu::DecimalFormat* NumberFormat::InitializeNumberFormat(
Isolate* isolate, Handle<String> locale, Handle<JSObject> options,
Handle<JSObject> resolved) {
@ -894,110 +839,6 @@ bool Intl::RemoveLocaleScriptTag(const std::string& icu_locale,
return true;
}
namespace {
Maybe<bool> IsPropertyUndefined(Isolate* isolate, Handle<JSObject> options,
const char* property) {
Factory* factory = isolate->factory();
// i. Let prop be the property name.
// ii. Let value be ? Get(options, prop).
Handle<Object> value;
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, value,
Object::GetPropertyOrElement(
isolate, options, factory->NewStringFromAsciiChecked(property)),
Nothing<bool>());
return Just(value->IsUndefined(isolate));
}
} // namespace
// ecma-402/#sec-todatetimeoptions
MaybeHandle<JSObject> DateFormat::ToDateTimeOptions(
Isolate* isolate, Handle<Object> input_options, const char* required,
const char* defaults) {
Factory* factory = isolate->factory();
// 1. If options is undefined, let options be null; otherwise let options be ?
// ToObject(options).
Handle<JSObject> options;
if (input_options->IsUndefined(isolate)) {
options = factory->NewJSObjectWithNullProto();
} else {
Handle<JSReceiver> options_obj;
ASSIGN_RETURN_ON_EXCEPTION(isolate, options_obj,
Object::ToObject(isolate, input_options),
JSObject);
// 2. Let options be ObjectCreate(options).
ASSIGN_RETURN_ON_EXCEPTION(isolate, options,
JSObject::ObjectCreate(isolate, options_obj),
JSObject);
}
// 3. Let needDefaults be true.
bool needs_default = true;
bool required_is_any = strcmp(required, "any") == 0;
// 4. If required is "date" or "any", then
if (required_is_any || (strcmp(required, "date") == 0)) {
// a. For each of the property names "weekday", "year", "month", "day", do
for (auto& prop : {"weekday", "year", "month", "day"}) {
// i. Let prop be the property name.
// ii. Let value be ? Get(options, prop)
Maybe<bool> maybe_undefined = IsPropertyUndefined(isolate, options, prop);
MAYBE_RETURN(maybe_undefined, Handle<JSObject>());
// iii. If value is not undefined, let needDefaults be false.
if (!maybe_undefined.FromJust()) {
needs_default = false;
}
}
}
// 5. If required is "time" or "any", then
if (required_is_any || (strcmp(required, "time") == 0)) {
// a. For each of the property names "hour", "minute", "second", do
for (auto& prop : {"hour", "minute", "second"}) {
// i. Let prop be the property name.
// ii. Let value be ? Get(options, prop)
Maybe<bool> maybe_undefined = IsPropertyUndefined(isolate, options, prop);
MAYBE_RETURN(maybe_undefined, Handle<JSObject>());
// iii. If value is not undefined, let needDefaults be false.
if (!maybe_undefined.FromJust()) {
needs_default = false;
}
}
}
// 6. If needDefaults is true and defaults is either "date" or "all", then
if (needs_default) {
bool default_is_all = strcmp(defaults, "all") == 0;
if (default_is_all || (strcmp(defaults, "date") == 0)) {
// a. For each of the property names "year", "month", "day", do
// i. Perform ? CreateDataPropertyOrThrow(options, prop, "numeric").
for (auto& prop : {"year", "month", "day"}) {
MAYBE_RETURN(
JSReceiver::CreateDataProperty(
isolate, options, factory->NewStringFromAsciiChecked(prop),
factory->numeric_string(), kThrowOnError),
Handle<JSObject>());
}
}
// 7. If needDefaults is true and defaults is either "time" or "all", then
if (default_is_all || (strcmp(defaults, "time") == 0)) {
// a. For each of the property names "hour", "minute", "second", do
// i. Perform ? CreateDataPropertyOrThrow(options, prop, "numeric").
for (auto& prop : {"hour", "minute", "second"}) {
MAYBE_RETURN(
JSReceiver::CreateDataProperty(
isolate, options, factory->NewStringFromAsciiChecked(prop),
factory->numeric_string(), kThrowOnError),
Handle<JSObject>());
}
}
}
// 8. Return options.
return options;
}
std::set<std::string> Intl::GetAvailableLocales(const IcuService& service) {
const icu::Locale* icu_available_locales = nullptr;
int32_t count = 0;
@ -1915,6 +1756,28 @@ bool IsAToZ(char ch) {
return IsInRange(AsciiAlphaToLower(ch), 'a', 'z');
}
// The following are temporary function calling back into js code in
// src/js/intl.js to call pre-existing functions until they are all moved to C++
// under src/objects/*.
// TODO(ftang): remove these temp function after bstell move them from js into
// C++
MaybeHandle<JSObject> CachedOrNewService(Isolate* isolate,
Handle<String> service,
Handle<Object> locales,
Handle<Object> options) {
Handle<Object> result;
Handle<Object> undefined_value(ReadOnlyRoots(isolate).undefined_value(),
isolate);
Handle<Object> args[] = {service, locales, options};
ASSIGN_RETURN_ON_EXCEPTION(
isolate, result,
Execution::Call(isolate, isolate->cached_or_new_service(),
undefined_value, arraysize(args), args),
JSArray);
return Handle<JSObject>::cast(result);
}
} // namespace
// Verifies that the input is a well-formed ISO 4217 currency code.
@ -1989,7 +1852,7 @@ MaybeHandle<Object> Intl::StringLocaleCompare(Isolate* isolate,
ASSIGN_RETURN_ON_EXCEPTION(
isolate, collator,
CachedOrNewService(isolate, factory->NewStringFromStaticChars("collator"),
locales, options, factory->undefined_value()),
locales, options),
Object);
CHECK(collator->IsJSCollator());
return Intl::CompareStrings(isolate, Handle<JSCollator>::cast(collator),
@ -2041,7 +1904,7 @@ MaybeHandle<String> Intl::NumberToLocaleString(Isolate* isolate,
isolate, number_format_holder,
CachedOrNewService(isolate,
factory->NewStringFromStaticChars("numberformat"),
locales, options, factory->undefined_value()),
locales, options),
String);
DCHECK(
Intl::IsObjectOfType(isolate, number_format_holder, Intl::kNumberFormat));

View File

@ -68,16 +68,6 @@ class DateFormat {
V8_WARN_UNUSED_RESULT static MaybeHandle<JSObject> Unwrap(
Isolate* isolate, Handle<JSReceiver> receiver, const char* method_name);
// ecma-402/#sec-todatetimeoptions
V8_WARN_UNUSED_RESULT static MaybeHandle<JSObject> ToDateTimeOptions(
Isolate* isolate, Handle<Object> input_options, const char* required,
const char* defaults);
V8_WARN_UNUSED_RESULT static MaybeHandle<String> ToLocaleDateTime(
Isolate* isolate, Handle<Object> date, Handle<Object> locales,
Handle<Object> options, const char* required, const char* defaults,
const char* service);
// Layout description.
#define DATE_FORMAT_FIELDS(V) \
V(kSimpleDateFormat, kPointerSize) \

View File

@ -487,36 +487,6 @@ RUNTIME_FUNCTION(Runtime_BreakIteratorBreakType) {
}
}
RUNTIME_FUNCTION(Runtime_ToLocaleDateTime) {
HandleScope scope(isolate);
DCHECK_EQ(6, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, date, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, locales, 1);
CONVERT_ARG_HANDLE_CHECKED(Object, options, 2);
CONVERT_ARG_HANDLE_CHECKED(String, required, 3);
CONVERT_ARG_HANDLE_CHECKED(String, defaults, 4);
CONVERT_ARG_HANDLE_CHECKED(String, service, 5);
RETURN_RESULT_OR_FAILURE(
isolate, DateFormat::ToLocaleDateTime(
isolate, date, locales, options, required->ToCString().get(),
defaults->ToCString().get(), service->ToCString().get()));
}
RUNTIME_FUNCTION(Runtime_ToDateTimeOptions) {
HandleScope scope(isolate);
DCHECK_EQ(args.length(), 3);
CONVERT_ARG_HANDLE_CHECKED(Object, options, 0);
CONVERT_ARG_HANDLE_CHECKED(String, required, 1);
CONVERT_ARG_HANDLE_CHECKED(String, defaults, 2);
RETURN_RESULT_OR_FAILURE(
isolate, DateFormat::ToDateTimeOptions(isolate, options,
required->ToCString().get(),
defaults->ToCString().get()));
}
RUNTIME_FUNCTION(Runtime_StringToLowerCaseIntl) {
HandleScope scope(isolate);
DCHECK_EQ(args.length(), 1);

View File

@ -405,26 +405,34 @@ RUNTIME_FUNCTION(Runtime_AddDictionaryProperty) {
RUNTIME_FUNCTION(Runtime_ObjectCreate) {
HandleScope scope(isolate);
Handle<Object> prototype = args.at(0);
Handle<Object> properties = args.at(1);
Handle<JSObject> obj;
// 1. If Type(O) is neither Object nor Null, throw a TypeError exception.
if (!prototype->IsNull(isolate) && !prototype->IsJSReceiver()) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, prototype));
}
// 2. Let obj be ObjectCreate(O).
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, obj, JSObject::ObjectCreate(isolate, prototype));
// 3. If Properties is not undefined, then
if (!properties->IsUndefined(isolate)) {
// a. Return ? ObjectDefineProperties(obj, Properties).
// Define the properties if properties was specified and is not undefined.
RETURN_RESULT_OR_FAILURE(
isolate, JSReceiver::DefineProperties(isolate, obj, properties));
// Generate the map with the specified {prototype} based on the Object
// function's initial map from the current native context.
// TODO(bmeurer): Use a dedicated cache for Object.create; think about
// slack tracking for Object.create.
Handle<Map> map =
Map::GetObjectCreateMap(isolate, Handle<HeapObject>::cast(prototype));
// Actually allocate the object.
Handle<JSObject> object;
if (map->is_dictionary_map()) {
object = isolate->factory()->NewSlowJSObjectFromMap(map);
} else {
object = isolate->factory()->NewJSObjectFromMap(map);
}
// 4. Return obj.
return *obj;
// Define the properties if properties was specified and is not undefined.
Handle<Object> properties = args.at(1);
if (!properties->IsUndefined(isolate)) {
RETURN_FAILURE_ON_EXCEPTION(
isolate, JSReceiver::DefineProperties(isolate, object, properties));
}
return *object;
}
MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate,

View File

@ -229,8 +229,6 @@ namespace internal {
F(ParseExtension, 1, 1) \
F(PluralRulesResolvedOptions, 1, 1) \
F(PluralRulesSelect, 2, 1) \
F(ToDateTimeOptions, 3, 1) \
F(ToLocaleDateTime, 6, 1) \
F(StringToLowerCaseIntl, 1, 1) \
F(StringToUpperCaseIntl, 1, 1) \
F(SupportedLocalesOf, 3, 1) \