summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/bindings/core/v8/to_v8_traits_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/bindings/core/v8/to_v8_traits_test.cc')
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/to_v8_traits_test.cc520
1 files changed, 520 insertions, 0 deletions
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/to_v8_traits_test.cc b/chromium/third_party/blink/renderer/bindings/core/v8/to_v8_traits_test.cc
new file mode 100644
index 00000000000..f30f06a51df
--- /dev/null
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/to_v8_traits_test.cc
@@ -0,0 +1,520 @@
+// 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