Fix Date BiDi format
1. Add `toISOString` to `v8::Date`. 2. Switch serialization to `ISOString`. Bug: v8:13043 Change-Id: I8a852f4a4a46bb3b8e5d52ef3cdffde7a408b403 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3749203 Auto-Submit: Maksim Sadym <sadym@chromium.org> Reviewed-by: Toon Verwaest <verwaest@chromium.org> Commit-Queue: Toon Verwaest <verwaest@chromium.org> Cr-Commit-Position: refs/heads/main@{#81647}
This commit is contained in:
parent
110fa66e13
commit
126d477925
@ -27,6 +27,11 @@ class V8_EXPORT Date : public Object {
|
||||
*/
|
||||
double ValueOf() const;
|
||||
|
||||
/**
|
||||
* Generates ISO string representation.
|
||||
*/
|
||||
v8::Local<v8::String> ToISOString() const;
|
||||
|
||||
V8_INLINE static Date* Cast(Value* value) {
|
||||
#ifdef V8_ENABLE_CHECKS
|
||||
CheckCast(value);
|
||||
|
@ -7280,6 +7280,20 @@ double v8::Date::ValueOf() const {
|
||||
return jsdate->value().Number();
|
||||
}
|
||||
|
||||
v8::Local<v8::String> v8::Date::ToISOString() const {
|
||||
i::Handle<i::Object> obj = Utils::OpenHandle(this);
|
||||
i::Handle<i::JSDate> jsdate = i::Handle<i::JSDate>::cast(obj);
|
||||
i::Isolate* i_isolate = jsdate->GetIsolate();
|
||||
API_RCS_SCOPE(i_isolate, Date, NumberValue);
|
||||
i::DateBuffer buffer =
|
||||
i::ToDateString(jsdate->value().Number(), i_isolate->date_cache(),
|
||||
i::ToDateStringMode::kISODateAndTime);
|
||||
i::Handle<i::String> str = i_isolate->factory()
|
||||
->NewStringFromUtf8(base::VectorOf(buffer))
|
||||
.ToHandleChecked();
|
||||
return Utils::ToLocal(str);
|
||||
}
|
||||
|
||||
// Assert that the static TimeZoneDetection cast in
|
||||
// DateTimeConfigurationChangeNotification is valid.
|
||||
#define TIME_ZONE_DETECTION_ASSERT_EQ(value) \
|
||||
|
@ -684,22 +684,10 @@ BUILTIN(DatePrototypeToISOString) {
|
||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
isolate, NewRangeError(MessageTemplate::kInvalidTimeValue));
|
||||
}
|
||||
int64_t const time_ms = static_cast<int64_t>(time_val);
|
||||
int year, month, day, weekday, hour, min, sec, ms;
|
||||
isolate->date_cache()->BreakDownTime(time_ms, &year, &month, &day, &weekday,
|
||||
&hour, &min, &sec, &ms);
|
||||
char buffer[128];
|
||||
if (year >= 0 && year <= 9999) {
|
||||
SNPrintF(base::ArrayVector(buffer), "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ",
|
||||
year, month + 1, day, hour, min, sec, ms);
|
||||
} else if (year < 0) {
|
||||
SNPrintF(base::ArrayVector(buffer), "-%06d-%02d-%02dT%02d:%02d:%02d.%03dZ",
|
||||
-year, month + 1, day, hour, min, sec, ms);
|
||||
} else {
|
||||
SNPrintF(base::ArrayVector(buffer), "+%06d-%02d-%02dT%02d:%02d:%02d.%03dZ",
|
||||
year, month + 1, day, hour, min, sec, ms);
|
||||
}
|
||||
return *isolate->factory()->NewStringFromAsciiChecked(buffer);
|
||||
DateBuffer buffer = ToDateString(time_val, isolate->date_cache(),
|
||||
ToDateStringMode::kISODateAndTime);
|
||||
RETURN_RESULT_OR_FAILURE(
|
||||
isolate, isolate->factory()->NewStringFromUtf8(base::VectorOf(buffer)));
|
||||
}
|
||||
|
||||
// ES6 section 20.3.4.41 Date.prototype.toString ( )
|
||||
|
@ -559,9 +559,10 @@ DateBuffer ToDateString(double time_val, DateCache* date_cache,
|
||||
return FormatDate("Invalid Date");
|
||||
}
|
||||
int64_t time_ms = static_cast<int64_t>(time_val);
|
||||
int64_t local_time_ms = mode != ToDateStringMode::kUTCDateAndTime
|
||||
? date_cache->ToLocal(time_ms)
|
||||
: time_ms;
|
||||
int64_t local_time_ms = (mode == ToDateStringMode::kUTCDateAndTime ||
|
||||
mode == ToDateStringMode::kISODateAndTime)
|
||||
? time_ms
|
||||
: date_cache->ToLocal(time_ms);
|
||||
int year, month, day, weekday, hour, min, sec, ms;
|
||||
date_cache->BreakDownTime(local_time_ms, &year, &month, &day, &weekday, &hour,
|
||||
&min, &sec, &ms);
|
||||
@ -590,6 +591,17 @@ DateBuffer ToDateString(double time_val, DateCache* date_cache,
|
||||
: "%s, %02d %s %04d %02d:%02d:%02d GMT",
|
||||
kShortWeekDays[weekday], day, kShortMonths[month], year,
|
||||
hour, min, sec);
|
||||
case ToDateStringMode::kISODateAndTime:
|
||||
if (year >= 0 && year <= 9999) {
|
||||
return FormatDate("%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", year,
|
||||
month + 1, day, hour, min, sec, ms);
|
||||
} else if (year < 0) {
|
||||
return FormatDate("-%06d-%02d-%02dT%02d:%02d:%02d.%03dZ", -year,
|
||||
month + 1, day, hour, min, sec, ms);
|
||||
} else {
|
||||
return FormatDate("+%06d-%02d-%02dT%02d:%02d:%02d.%03dZ", year,
|
||||
month + 1, day, hour, min, sec, ms);
|
||||
}
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
@ -255,6 +255,7 @@ enum class ToDateStringMode {
|
||||
kLocalTime,
|
||||
kLocalDateAndTime,
|
||||
kUTCDateAndTime,
|
||||
kISODateAndTime
|
||||
};
|
||||
|
||||
// ES6 section 20.3.4.41.1 ToDateString(tv)
|
||||
|
@ -40,12 +40,10 @@ std::unique_ptr<protocol::Value> DescriptionForDate(
|
||||
v8::Local<v8::Context> context, v8::Local<v8::Date> date) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
v8::TryCatch tryCatch(isolate);
|
||||
v8::Local<v8::String> description;
|
||||
bool success = date->ToString(context).ToLocal(&description);
|
||||
DCHECK(success);
|
||||
USE(success);
|
||||
|
||||
return protocol::StringValue::create(toProtocolString(isolate, description));
|
||||
v8::Local<v8::String> dateISOString = date->ToISOString();
|
||||
return protocol::StringValue::create(
|
||||
toProtocolString(isolate, dateISOString));
|
||||
}
|
||||
|
||||
String16 _descriptionForRegExpFlags(v8::Local<v8::RegExp> value) {
|
||||
|
@ -306,14 +306,39 @@ Runtime.callFunctionOn
|
||||
}
|
||||
|
||||
Running test: Date
|
||||
testing date: Thu Apr 07 2022 16:16:25 GMT+1100
|
||||
Expected date in GMT: Thu, 07 Apr 2022 05:16:25 GMT
|
||||
Date type as expected: true
|
||||
Date value as expected: true
|
||||
testing date: Thu Apr 07 2022 16:16:25 GMT-1100
|
||||
Expected date in GMT: Fri, 08 Apr 2022 03:16:25 GMT
|
||||
Date type as expected: true
|
||||
Date value as expected: true
|
||||
testing expression: new Date('Thu Apr 07 2022 16:17:18 GMT')
|
||||
Runtime.evaluate
|
||||
{
|
||||
type : date
|
||||
value : 2022-04-07T16:17:18.000Z
|
||||
}
|
||||
Runtime.callFunctionOn
|
||||
{
|
||||
type : date
|
||||
value : 2022-04-07T16:17:18.000Z
|
||||
}
|
||||
testing expression: new Date('Thu Apr 07 2022 16:17:18 GMT+1100')
|
||||
Runtime.evaluate
|
||||
{
|
||||
type : date
|
||||
value : 2022-04-07T05:17:18.000Z
|
||||
}
|
||||
Runtime.callFunctionOn
|
||||
{
|
||||
type : date
|
||||
value : 2022-04-07T05:17:18.000Z
|
||||
}
|
||||
testing expression: new Date('Thu Apr 07 2022 16:17:18 GMT-1100')
|
||||
Runtime.evaluate
|
||||
{
|
||||
type : date
|
||||
value : 2022-04-08T03:17:18.000Z
|
||||
}
|
||||
Runtime.callFunctionOn
|
||||
{
|
||||
type : date
|
||||
value : 2022-04-08T03:17:18.000Z
|
||||
}
|
||||
|
||||
Running test: Error
|
||||
testing expression: [new Error(), new Error('qwe')]
|
||||
|
@ -35,9 +35,9 @@ InspectorTest.runAsyncTestSuite([
|
||||
await testExpression("[new RegExp('ab+c'), new RegExp('ab+c', 'ig')]");
|
||||
},
|
||||
async function Date() {
|
||||
// Serialization depends on the timezone, so0 manual vreification is needed.
|
||||
await testDate("Thu Apr 07 2022 16:16:25 GMT+1100");
|
||||
await testDate("Thu Apr 07 2022 16:16:25 GMT-1100");
|
||||
await testExpression("new Date('Thu Apr 07 2022 16:17:18 GMT')");
|
||||
await testExpression("new Date('Thu Apr 07 2022 16:17:18 GMT+1100')");
|
||||
await testExpression("new Date('Thu Apr 07 2022 16:17:18 GMT-1100')");
|
||||
},
|
||||
async function Error() {
|
||||
await testExpression("[new Error(), new Error('qwe')]");
|
||||
@ -73,26 +73,6 @@ InspectorTest.runAsyncTestSuite([
|
||||
await testExpression("{key_level_1: {key_level_2: {key_level_3: 'value_level_3'}}}");
|
||||
}]);
|
||||
|
||||
async function testDate(dateStr) {
|
||||
// TODO(sadym): make the test timezone-agnostic. Current approach is not 100% valid, as it relies on the `date.ToString` implementation.
|
||||
InspectorTest.logMessage("testing date: " + dateStr);
|
||||
const serializedDate = (await serializeViaEvaluate("new Date('" + dateStr + "')")).result.result.webDriverValue;
|
||||
// Expected format: {
|
||||
// type: "date"
|
||||
// value: "Fri Apr 08 2022 03:16:25 GMT+0000 (Coordinated Universal Time)"
|
||||
// }
|
||||
const expectedDateStr = new Date(dateStr).toString();
|
||||
|
||||
InspectorTest.logMessage("Expected date in GMT: " + (new Date(dateStr).toGMTString()));
|
||||
InspectorTest.logMessage("Date type as expected: " + (serializedDate.type === "date"));
|
||||
if (serializedDate.value === expectedDateStr) {
|
||||
InspectorTest.logMessage("Date value as expected: " + (serializedDate.value === expectedDateStr));
|
||||
} else {
|
||||
InspectorTest.logMessage("Error. Eexpected " + expectedDateStr + ", but was " + serializedDate.value);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
async function serializeViaEvaluate(expression) {
|
||||
return await Protocol.Runtime.evaluate({
|
||||
expression: "("+expression+")",
|
||||
|
Loading…
Reference in New Issue
Block a user