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:
parent
fcfd995aa1
commit
41b3955fbf
@ -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');
|
||||
}
|
||||
);
|
||||
|
@ -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());
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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) \
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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) \
|
||||
|
Loading…
Reference in New Issue
Block a user