blob: f30f06a51df312809d920e1093bd2818c6137da1 [file] [log] [blame]
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h"
#include "third_party/blink/renderer/bindings/core/v8/file_or_usv_string_or_form_data.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_address_space.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_create_html_callback.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_dom_point_init.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_event_listener.h"
#include "third_party/blink/renderer/core/dom/events/event_target.h"
#include "third_party/blink/renderer/core/streams/stream_promise_resolver.h"
#include "third_party/blink/renderer/core/testing/garbage_collected_script_wrappable.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/platform/bindings/dictionary_base.h"
namespace blink {
namespace {
#define TEST_TOV8_TRAITS(scope, IDLType, expected, value) \
TestToV8Traits<IDLType>(scope, expected, value, __FILE__, __LINE__)
template <typename IDLType, typename T>
void TestToV8Traits(const V8TestingScope& scope,
const String& expected,
T value,
const char* path,
int line_number) {
v8::Local<v8::Value> actual;
if (!ToV8Traits<IDLType>::ToV8(scope.GetScriptState(), value)
.ToLocal(&actual)) {
ADD_FAILURE_AT(path, line_number) << "ToV8 throws an exception.";
return;
}
String actual_string =
ToCoreString(actual->ToString(scope.GetContext()).ToLocalChecked());
if (expected != actual_string) {
ADD_FAILURE_AT(path, line_number)
<< "ToV8 returns an incorrect value.\n Actual: "
<< actual_string.Utf8() << "\nExpected: " << expected;
return;
}
}
TEST(ToV8TraitsTest, Any) {
const V8TestingScope scope;
ScriptValue value(scope.GetIsolate(),
v8::Number::New(scope.GetIsolate(), 1234.0));
v8::Local<v8::Value> actual1;
ASSERT_TRUE(ToV8Traits<IDLAny>::ToV8(scope.GetScriptState(), value)
.ToLocal(&actual1));
EXPECT_FALSE(actual1.IsEmpty());
double actual_as_number1 = actual1.As<v8::Number>()->Value();
EXPECT_EQ(1234.0, actual_as_number1);
}
TEST(ToV8TraitsTest, Boolean) {
const V8TestingScope scope;
TEST_TOV8_TRAITS(scope, IDLBoolean, "true", true);
TEST_TOV8_TRAITS(scope, IDLBoolean, "false", false);
}
TEST(ToV8TraitsTest, Integer) {
const V8TestingScope scope;
// Test type matching
// Integer
TEST_TOV8_TRAITS(scope, IDLByte, "0", static_cast<int8_t>(0));
TEST_TOV8_TRAITS(scope, IDLByte, "1", static_cast<int8_t>(1));
TEST_TOV8_TRAITS(scope, IDLByte, "-2", static_cast<int8_t>(-2));
TEST_TOV8_TRAITS(scope, IDLShort, "0", static_cast<int16_t>(0));
TEST_TOV8_TRAITS(scope, IDLLong, "0", static_cast<int32_t>(0));
TEST_TOV8_TRAITS(scope, IDLLongLong, "0", static_cast<int64_t>(0));
TEST_TOV8_TRAITS(scope, IDLOctet, "0", static_cast<uint8_t>(0));
TEST_TOV8_TRAITS(scope, IDLUnsignedShort, "0", static_cast<uint16_t>(0));
TEST_TOV8_TRAITS(scope, IDLUnsignedLong, "0", static_cast<uint32_t>(0));
TEST_TOV8_TRAITS(scope, IDLUnsignedLongLong, "0", static_cast<uint64_t>(0));
// [Clamp] Integer
TEST_TOV8_TRAITS(scope, IDLByteClamp, "0", static_cast<int8_t>(0));
TEST_TOV8_TRAITS(scope, IDLShortClamp, "0", static_cast<int16_t>(0));
TEST_TOV8_TRAITS(scope, IDLLongClamp, "0", static_cast<int32_t>(0));
TEST_TOV8_TRAITS(scope, IDLLongLongClamp, "0", static_cast<int64_t>(0));
TEST_TOV8_TRAITS(scope, IDLOctetClamp, "0", static_cast<uint8_t>(0));
TEST_TOV8_TRAITS(scope, IDLUnsignedShortClamp, "0", static_cast<uint16_t>(0));
TEST_TOV8_TRAITS(scope, IDLUnsignedLongClamp, "0", static_cast<uint32_t>(0));
TEST_TOV8_TRAITS(scope, IDLUnsignedLongLongClamp, "0",
static_cast<uint64_t>(0));
// [EnforceRange] Integer
TEST_TOV8_TRAITS(scope, IDLByteEnforceRange, "0", static_cast<int8_t>(0));
TEST_TOV8_TRAITS(scope, IDLShortEnforceRange, "0", static_cast<int16_t>(0));
TEST_TOV8_TRAITS(scope, IDLLongEnforceRange, "0", static_cast<int32_t>(0));
TEST_TOV8_TRAITS(scope, IDLLongLongEnforceRange, "0",
static_cast<int64_t>(0));
TEST_TOV8_TRAITS(scope, IDLOctetEnforceRange, "0", static_cast<uint8_t>(0));
TEST_TOV8_TRAITS(scope, IDLUnsignedShortEnforceRange, "0",
static_cast<uint16_t>(0));
TEST_TOV8_TRAITS(scope, IDLUnsignedLongEnforceRange, "0",
static_cast<uint32_t>(0));
TEST_TOV8_TRAITS(scope, IDLUnsignedLongLongEnforceRange, "0",
static_cast<uint64_t>(0));
// Test the maximum and the minimum integer in the range
TEST_TOV8_TRAITS(scope, IDLLong, "-2147483648",
std::numeric_limits<int32_t>::min());
TEST_TOV8_TRAITS(scope, IDLLong, "2147483647",
std::numeric_limits<int32_t>::max());
TEST_TOV8_TRAITS(scope, IDLUnsignedLong, "4294967295",
std::numeric_limits<uint32_t>::max());
// v8::Number can represent exact numbers in [-(2^53-1), 2^53-1].
TEST_TOV8_TRAITS(scope, IDLLongLong, "-9007199254740991",
static_cast<int64_t>(-9007199254740991)); // -(2^53-1)
TEST_TOV8_TRAITS(scope, IDLLongLong, "9007199254740991",
static_cast<int64_t>(9007199254740991)); // 2^53-1
TEST_TOV8_TRAITS(scope, IDLUnsignedLongLong, "9007199254740991",
static_cast<uint64_t>(9007199254740991)); // 2^53-1
}
TEST(ToV8TraitsTest, FloatAndDouble) {
const V8TestingScope scope;
TEST_TOV8_TRAITS(scope, IDLFloat, "0.5", static_cast<float>(0.5));
TEST_TOV8_TRAITS(scope, IDLUnrestrictedFloat, "-0.5",
static_cast<float>(-0.5));
TEST_TOV8_TRAITS(scope, IDLDouble, "0.5", static_cast<double>(0.5));
TEST_TOV8_TRAITS(scope, IDLUnrestrictedDouble, "-0.5",
static_cast<double>(-0.5));
TEST_TOV8_TRAITS(scope, IDLUnrestrictedDouble, "NaN",
std::numeric_limits<double>::quiet_NaN());
TEST_TOV8_TRAITS(scope, IDLUnrestrictedDouble, "Infinity",
std::numeric_limits<double>::infinity());
TEST_TOV8_TRAITS(scope, IDLUnrestrictedDouble, "-Infinity",
-std::numeric_limits<double>::infinity());
}
TEST(ToV8TraitsTest, String) {
const V8TestingScope scope;
const String string("string");
const char* const charptr_string = "charptrString";
// ByteString
TEST_TOV8_TRAITS(scope, IDLByteStringV2, "string", string);
TEST_TOV8_TRAITS(scope, IDLByteStringV2, "charptrString", charptr_string);
// DOMString
TEST_TOV8_TRAITS(scope, IDLStringV2, "string", string);
TEST_TOV8_TRAITS(scope, IDLStringV2, "charptrString", charptr_string);
TEST_TOV8_TRAITS(scope, IDLStringTreatNullAsEmptyStringV2, "string", string);
TEST_TOV8_TRAITS(scope, IDLStringTreatNullAsEmptyStringV2, "charptrString",
charptr_string);
// USVString
TEST_TOV8_TRAITS(scope, IDLUSVStringV2, "string", string);
TEST_TOV8_TRAITS(scope, IDLUSVStringV2, "charptrString", charptr_string);
// [StringContext=TrustedHTML] DOMString
TEST_TOV8_TRAITS(scope, IDLStringStringContextTrustedHTMLV2, "string",
string);
TEST_TOV8_TRAITS(scope, IDLStringStringContextTrustedHTMLV2, "charptrString",
charptr_string);
TEST_TOV8_TRAITS(scope,
IDLStringStringContextTrustedHTMLTreatNullAsEmptyStringV2,
"string", string);
TEST_TOV8_TRAITS(scope,
IDLStringStringContextTrustedHTMLTreatNullAsEmptyStringV2,
"charptrString", charptr_string);
// [StringContext=TrustedScript] DOMString
TEST_TOV8_TRAITS(scope, IDLStringStringContextTrustedScriptV2, "string",
string);
TEST_TOV8_TRAITS(scope, IDLStringStringContextTrustedScriptV2,
"charptrString", charptr_string);
TEST_TOV8_TRAITS(scope,
IDLStringStringContextTrustedScriptTreatNullAsEmptyStringV2,
"string", string);
TEST_TOV8_TRAITS(scope,
IDLStringStringContextTrustedScriptTreatNullAsEmptyStringV2,
"charptrString", charptr_string);
// [StringContext=TrustedScriptURL] USVString
TEST_TOV8_TRAITS(scope, IDLUSVStringStringContextTrustedScriptURLV2, "string",
string);
TEST_TOV8_TRAITS(scope, IDLUSVStringStringContextTrustedScriptURLV2,
"charptrString", charptr_string);
}
TEST(ToV8TraitsTest, EmptyString) {
const V8TestingScope scope;
const String empty_string("");
TEST_TOV8_TRAITS(scope, IDLStringV2, "", empty_string);
const char* const empty = "";
TEST_TOV8_TRAITS(scope, IDLStringV2, "", empty);
}
TEST(ToV8TraitsTest, Object) {
const V8TestingScope scope;
Vector<String> string_vector;
string_vector.push_back("hello");
string_vector.push_back("world");
ScriptValue value(scope.GetIsolate(),
ToV8Traits<IDLSequence<IDLStringV2>>::ToV8(
scope.GetScriptState(), string_vector));
TEST_TOV8_TRAITS(scope, IDLObject, "hello,world", value);
v8::Local<v8::Value> actual;
ASSERT_TRUE(ToV8Traits<IDLObject>::ToV8(scope.GetScriptState(), value)
.ToLocal(&actual));
EXPECT_TRUE(actual->IsObject());
}
TEST(ToV8TraitsTest, Promise) {
const V8TestingScope scope;
ScriptPromise::InternalResolver resolver(scope.GetScriptState());
ScriptPromise promise = resolver.Promise();
TEST_TOV8_TRAITS(scope, IDLPromise, "[object Promise]", promise);
}
TEST(ToV8TraitsTest, NotShared) {
const V8TestingScope scope;
auto not_shared = NotShared<DOMUint8Array>(DOMUint8Array::Create(2));
not_shared->Data()[0] = static_cast<uint8_t>(0);
not_shared->Data()[1] = static_cast<uint8_t>(255);
TEST_TOV8_TRAITS(scope, NotShared<DOMUint8Array>, "0,255", not_shared);
}
TEST(ToV8TraitsTest, MaybeShared) {
const V8TestingScope scope;
auto maybe_shared = MaybeShared<DOMInt8Array>(DOMInt8Array::Create(3));
maybe_shared->Data()[0] = static_cast<int8_t>(-128);
maybe_shared->Data()[1] = static_cast<int8_t>(0);
maybe_shared->Data()[2] = static_cast<int8_t>(127);
TEST_TOV8_TRAITS(scope, MaybeShared<DOMInt8Array>, "-128,0,127",
maybe_shared);
}
TEST(ToV8TraitsTest, Vector) {
const V8TestingScope scope;
Vector<String> string_vector;
string_vector.push_back("foo");
string_vector.push_back("bar");
TEST_TOV8_TRAITS(scope, IDLSequence<IDLStringV2>, "foo,bar", string_vector);
}
TEST(ToV8TraitsTest, HeapVector) {
const V8TestingScope scope;
HeapVector<Member<GarbageCollectedScriptWrappable>> heap_vector;
heap_vector.push_back(
MakeGarbageCollected<GarbageCollectedScriptWrappable>("hoge"));
heap_vector.push_back(
MakeGarbageCollected<GarbageCollectedScriptWrappable>("fuga"));
TEST_TOV8_TRAITS(scope, IDLSequence<GarbageCollectedScriptWrappable>,
"hoge,fuga", heap_vector);
HeapVector<Member<GarbageCollectedScriptWrappable>>*
garbage_collected_heap_vector = &heap_vector;
TEST_TOV8_TRAITS(scope, IDLSequence<GarbageCollectedScriptWrappable>,
"hoge,fuga", garbage_collected_heap_vector);
}
TEST(ToV8TraitsTest, BasicIDLTypeVectors) {
const V8TestingScope scope;
Vector<int32_t> int32_vector;
int32_vector.push_back(42);
int32_vector.push_back(23);
TEST_TOV8_TRAITS(scope, IDLSequence<IDLLong>, "42,23", int32_vector);
Vector<int64_t> int64_vector;
int64_vector.push_back(31773);
int64_vector.push_back(404);
TEST_TOV8_TRAITS(scope, IDLSequence<IDLLongLong>, "31773,404", int64_vector);
Vector<uint32_t> uint32_vector;
uint32_vector.push_back(1);
uint32_vector.push_back(2);
TEST_TOV8_TRAITS(scope, IDLSequence<IDLUnsignedLong>, "1,2", uint32_vector);
Vector<uint64_t> uint64_vector;
uint64_vector.push_back(1001);
uint64_vector.push_back(2002);
TEST_TOV8_TRAITS(scope, IDLSequence<IDLUnsignedLongLong>, "1001,2002",
uint64_vector);
Vector<float> float_vector;
float_vector.push_back(0.125);
float_vector.push_back(1.);
TEST_TOV8_TRAITS(scope, IDLSequence<IDLFloat>, "0.125,1", float_vector);
Vector<double> double_vector;
double_vector.push_back(2.3);
double_vector.push_back(4.2);
TEST_TOV8_TRAITS(scope, IDLSequence<IDLDouble>, "2.3,4.2", double_vector);
Vector<bool> bool_vector;
bool_vector.push_back(true);
bool_vector.push_back(true);
bool_vector.push_back(false);
TEST_TOV8_TRAITS(scope, IDLSequence<IDLBoolean>, "true,true,false",
bool_vector);
}
TEST(ToV8TraitsTest, StringVectorVector) {
const V8TestingScope scope;
Vector<String> string_vector1;
string_vector1.push_back("foo");
string_vector1.push_back("bar");
Vector<String> string_vector2;
string_vector2.push_back("quux");
Vector<Vector<String>> compound_vector;
compound_vector.push_back(string_vector1);
compound_vector.push_back(string_vector2);
EXPECT_EQ(2U, compound_vector.size());
TEST_TOV8_TRAITS(scope, IDLSequence<IDLSequence<IDLStringV2>>, "foo,bar,quux",
compound_vector);
v8::Local<v8::Value> actual;
ASSERT_TRUE(ToV8Traits<IDLSequence<IDLSequence<IDLStringV2>>>::ToV8(
scope.GetScriptState(), compound_vector)
.ToLocal(&actual))
<< "ToV8 throws an exception.";
v8::Local<v8::Object> result =
actual->ToObject(scope.GetContext()).ToLocalChecked();
v8::Local<v8::Value> vector1 =
result->Get(scope.GetContext(), 0).ToLocalChecked();
EXPECT_TRUE(vector1->IsArray());
EXPECT_EQ(2U, vector1.As<v8::Array>()->Length());
v8::Local<v8::Value> vector2 =
result->Get(scope.GetContext(), 1).ToLocalChecked();
EXPECT_TRUE(vector2->IsArray());
EXPECT_EQ(1U, vector2.As<v8::Array>()->Length());
}
TEST(ToV8TraitsTest, PairVector) {
const V8TestingScope scope;
Vector<std::pair<String, int8_t>> pair_vector;
pair_vector.push_back(std::make_pair("one", 1));
pair_vector.push_back(std::make_pair("two", 2));
using ByteRecord = IDLRecord<IDLStringV2, IDLByte>;
TEST_TOV8_TRAITS(scope, ByteRecord, "[object Object]", pair_vector);
v8::Local<v8::Value> actual;
ASSERT_TRUE(ToV8Traits<ByteRecord>::ToV8(scope.GetScriptState(), pair_vector)
.ToLocal(&actual))
<< "ToV8 throws an exception.";
v8::Local<v8::Object> result =
actual->ToObject(scope.GetContext()).ToLocalChecked();
v8::Local<v8::Value> one =
result->Get(scope.GetContext(), V8String(scope.GetIsolate(), "one"))
.ToLocalChecked();
EXPECT_EQ(1, one->NumberValue(scope.GetContext()).FromJust());
v8::Local<v8::Value> two =
result->Get(scope.GetContext(), V8String(scope.GetIsolate(), "two"))
.ToLocalChecked();
EXPECT_EQ(2, two->NumberValue(scope.GetContext()).FromJust());
}
TEST(ToV8TraitsTest, PairHeapVector) {
const V8TestingScope scope;
HeapVector<std::pair<String, Member<GarbageCollectedScriptWrappable>>>
pair_heap_vector;
pair_heap_vector.push_back(std::make_pair(
"one", MakeGarbageCollected<GarbageCollectedScriptWrappable>("foo")));
pair_heap_vector.push_back(std::make_pair(
"two", MakeGarbageCollected<GarbageCollectedScriptWrappable>("bar")));
using HeapRecord = IDLRecord<IDLStringV2, GarbageCollectedScriptWrappable>;
TEST_TOV8_TRAITS(scope, HeapRecord, "[object Object]", pair_heap_vector);
v8::Local<v8::Value> actual;
ASSERT_TRUE(
ToV8Traits<HeapRecord>::ToV8(scope.GetScriptState(), pair_heap_vector)
.ToLocal(&actual))
<< "ToV8 throws an exception.";
v8::Local<v8::Object> result =
actual->ToObject(scope.GetContext()).ToLocalChecked();
v8::Local<v8::Value> one =
result->Get(scope.GetContext(), V8String(scope.GetIsolate(), "one"))
.ToLocalChecked();
EXPECT_TRUE(one->IsObject());
EXPECT_EQ(String("foo"),
ToCoreString(one->ToString(scope.GetContext()).ToLocalChecked()));
v8::Local<v8::Value> two =
result->Get(scope.GetContext(), V8String(scope.GetIsolate(), "two"))
.ToLocalChecked();
EXPECT_TRUE(two->IsObject());
EXPECT_EQ(String("bar"),
ToCoreString(two->ToString(scope.GetContext()).ToLocalChecked()));
HeapVector<std::pair<String, Member<GarbageCollectedScriptWrappable>>>*
garbage_collected_pair_heap_vector = &pair_heap_vector;
TEST_TOV8_TRAITS(scope, HeapRecord, "[object Object]",
garbage_collected_pair_heap_vector);
}
TEST(ToV8TraitsTest, NullStringInputForNoneNullableType) {
const V8TestingScope scope;
const String null_string;
TEST_TOV8_TRAITS(scope, IDLStringV2, "", null_string);
const char* const null = nullptr;
TEST_TOV8_TRAITS(scope, IDLStringV2, "", null);
}
TEST(ToV8TraitsTest, Nullable) {
const V8TestingScope scope;
// Nullable Boolean
TEST_TOV8_TRAITS(scope, IDLNullable<IDLBoolean>, "null", base::nullopt);
TEST_TOV8_TRAITS(scope, IDLNullable<IDLBoolean>, "true", true);
// Nullable Integer
TEST_TOV8_TRAITS(scope, IDLNullable<IDLByte>, "null", base::nullopt);
TEST_TOV8_TRAITS(scope, IDLNullable<IDLUnsignedLong>, "0",
base::Optional<uint32_t>(0));
// Nullable Float
TEST_TOV8_TRAITS(scope, IDLNullable<IDLFloat>, "null", base::nullopt);
TEST_TOV8_TRAITS(scope, IDLNullable<IDLFloat>, "0.5",
base::Optional<float>(0.5));
// Nullable Double
TEST_TOV8_TRAITS(scope, IDLNullable<IDLDouble>, "null", base::nullopt);
TEST_TOV8_TRAITS(scope, IDLNullable<IDLDouble>, "3.14",
base::Optional<double>(3.14));
}
TEST(ToV8TraitsTest, NullableString) {
const V8TestingScope scope;
TEST_TOV8_TRAITS(scope, IDLNullable<IDLStringV2>, "null", String());
TEST_TOV8_TRAITS(scope, IDLNullable<IDLStringV2>, "string", String("string"));
TEST_TOV8_TRAITS(scope, IDLNullable<IDLStringV2>, "", String(""));
const char* const null = nullptr;
TEST_TOV8_TRAITS(scope, IDLNullable<IDLStringV2>, "null", null);
const char* const charptr_string = "charptrString";
TEST_TOV8_TRAITS(scope, IDLNullable<IDLStringV2>, "charptrString",
charptr_string);
const char* const charptr_empty_string = "";
TEST_TOV8_TRAITS(scope, IDLNullable<IDLStringV2>, "", charptr_empty_string);
}
TEST(ToV8TraitsTest, NullableScriptWrappable) {
const V8TestingScope scope;
TEST_TOV8_TRAITS(scope, IDLNullable<EventTarget>, "null", nullptr);
EventTarget* event_target = EventTarget::Create(scope.GetScriptState());
TEST_TOV8_TRAITS(scope, IDLNullable<EventTarget>, "[object EventTarget]",
event_target);
}
TEST(ToV8TraitsTest, NullableDictionary) {
const V8TestingScope scope;
// bindings::DictionaryBase
TEST_TOV8_TRAITS(scope, IDLNullable<bindings::DictionaryBase>, "null",
nullptr);
// IDLDictionaryBase
DOMPointInit* dom_point_init = DOMPointInit::Create();
TEST_TOV8_TRAITS(scope, IDLNullable<DOMPointInit>, "null", nullptr);
TEST_TOV8_TRAITS(scope, IDLNullable<DOMPointInit>, "[object Object]",
dom_point_init);
}
TEST(ToV8TraitsTest, NullableCallbackFunction) {
const V8TestingScope scope;
TEST_TOV8_TRAITS(scope, IDLNullable<V8CreateHTMLCallback>, "null", nullptr);
V8CreateHTMLCallback* v8_create_html_callback =
V8CreateHTMLCallback::Create(scope.GetContext()->Global());
TEST_TOV8_TRAITS(scope, IDLNullable<V8CreateHTMLCallback>, "[object Window]",
v8_create_html_callback);
}
TEST(ToV8TraitsTest, NullableCallbackInterface) {
const V8TestingScope scope;
TEST_TOV8_TRAITS(scope, IDLNullable<V8CreateHTMLCallback>, "null", nullptr);
V8EventListener* v8_event_listener =
V8EventListener::Create(scope.GetContext()->Global());
TEST_TOV8_TRAITS(scope, IDLNullable<V8EventListener>, "[object Window]",
v8_event_listener);
}
TEST(ToV8TraitsTest, NullableEnumeration) {
const V8TestingScope scope;
TEST_TOV8_TRAITS(scope, IDLNullable<V8AddressSpace>, "null", base::nullopt);
const base::Optional<V8AddressSpace> v8_address_space =
V8AddressSpace::Create("public");
TEST_TOV8_TRAITS(scope, IDLNullable<V8AddressSpace>, "public",
v8_address_space);
}
TEST(ToV8TraitsTest, NullableDate) {
const V8TestingScope scope;
TEST_TOV8_TRAITS(scope, IDLNullable<IDLDate>, "null", base::nullopt);
base::Time expected_date;
EXPECT_TRUE(
base::Time::FromString("Fri, 01 Jan 2021 00:00:00 GMT", &expected_date));
v8::Local<v8::Value> result;
ASSERT_TRUE(
ToV8Traits<IDLNullable<IDLDate>>::ToV8(
scope.GetScriptState(), base::Optional<base::Time>(expected_date))
.ToLocal(&result));
String actual_string =
ToCoreString(result->ToString(scope.GetContext()).ToLocalChecked());
base::Time actual_date;
EXPECT_TRUE(
base::Time::FromString(actual_string.Ascii().c_str(), &actual_date));
EXPECT_EQ(expected_date, actual_date);
}
TEST(ToV8TraitsTest, Union) {
const V8TestingScope scope;
const FileOrUSVStringOrFormData usv_string =
FileOrUSVStringOrFormData::FromUSVString("https://example.com/");
TEST_TOV8_TRAITS(scope, IDLUnionNotINT<FileOrUSVStringOrFormData>,
"https://example.com/", usv_string);
}
TEST(ToV8TraitsTest, Optional) {
const V8TestingScope scope;
TEST_TOV8_TRAITS(scope, IDLOptional<DOMPointInit>, "undefined", nullptr);
DOMPointInit* dom_point_init = DOMPointInit::Create();
TEST_TOV8_TRAITS(scope, IDLOptional<DOMPointInit>, "[object Object]",
dom_point_init);
TEST_TOV8_TRAITS(scope, IDLOptional<IDLAny>, "undefined", ScriptValue());
ScriptValue value(scope.GetIsolate(),
v8::Number::New(scope.GetIsolate(), 3.14));
TEST_TOV8_TRAITS(scope, IDLOptional<IDLAny>, "3.14", value);
}
} // namespace
} // namespace blink