OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "bindings/core/v8/NativeValueTraitsImpl.h" |
| 6 |
| 7 #include <utility> |
| 8 #include "bindings/core/v8/ExceptionState.h" |
| 9 #include "bindings/core/v8/IDLTypes.h" |
| 10 #include "bindings/core/v8/ToV8.h" |
| 11 #include "bindings/core/v8/V8BindingForTesting.h" |
| 12 #include "testing/gtest/include/gtest/gtest.h" |
| 13 #include "wtf/Vector.h" |
| 14 |
| 15 namespace blink { |
| 16 |
| 17 namespace { |
| 18 |
| 19 template <typename T> |
| 20 v8::Local<v8::Value> ToV8(V8TestingScope* scope, T value) { |
| 21 return blink::ToV8(value, scope->context()->Global(), scope->isolate()); |
| 22 } |
| 23 |
| 24 void ThrowException(v8::Local<v8::Name>, |
| 25 const v8::PropertyCallbackInfo<v8::Value>& info) { |
| 26 info.GetIsolate()->ThrowException(v8String(info.GetIsolate(), "bogus!")); |
| 27 } |
| 28 |
| 29 void ReturnBogusObjectDescriptor( |
| 30 const v8::FunctionCallbackInfo<v8::Value>& info) { |
| 31 v8::Isolate* isolate = info.GetIsolate(); |
| 32 auto context = isolate->GetCurrentContext(); |
| 33 |
| 34 v8::Local<v8::Object> descriptor = v8::Object::New(isolate); |
| 35 EXPECT_TRUE( |
| 36 v8CallBoolean(descriptor->Set(context, v8String(isolate, "configurable"), |
| 37 v8::Boolean::New(isolate, true)))); |
| 38 EXPECT_TRUE(v8CallBoolean(descriptor->SetAccessor( |
| 39 context, v8String(isolate, "enumerable"), ThrowException))); |
| 40 info.GetReturnValue().Set(descriptor); |
| 41 } |
| 42 |
| 43 TEST(NativeValueTraitsImplTest, IDLRecord) { |
| 44 V8TestingScope scope; |
| 45 { |
| 46 v8::Local<v8::Object> v8Object = v8::Object::New(scope.isolate()); |
| 47 NonThrowableExceptionState exceptionState; |
| 48 const auto& record = |
| 49 NativeValueTraits<IDLRecord<IDLString, IDLOctet>>::nativeValue( |
| 50 scope.isolate(), v8Object, exceptionState); |
| 51 EXPECT_TRUE(record.isEmpty()); |
| 52 } |
| 53 { |
| 54 v8::Local<v8::Object> v8Object = v8::Object::New(scope.isolate()); |
| 55 EXPECT_TRUE(v8CallBoolean( |
| 56 v8Object->Set(scope.context(), ToV8(&scope, "foo"), ToV8(&scope, 34)))); |
| 57 EXPECT_TRUE(v8CallBoolean(v8Object->Set( |
| 58 scope.context(), ToV8(&scope, "bar"), ToV8(&scope, -1024)))); |
| 59 EXPECT_TRUE(v8CallBoolean( |
| 60 v8Object->Set(scope.context(), ToV8(&scope, "foo"), ToV8(&scope, 42)))); |
| 61 |
| 62 NonThrowableExceptionState exceptionState; |
| 63 const auto& record = |
| 64 NativeValueTraits<IDLRecord<IDLByteString, IDLLong>>::nativeValue( |
| 65 scope.isolate(), v8Object, exceptionState); |
| 66 EXPECT_EQ(2U, record.size()); |
| 67 EXPECT_EQ(std::make_pair(String("foo"), int32_t(42)), record[0]); |
| 68 EXPECT_EQ(std::make_pair(String("bar"), int32_t(-1024)), record[1]); |
| 69 } |
| 70 { |
| 71 v8::Local<v8::Object> v8Object = v8::Object::New(scope.isolate()); |
| 72 EXPECT_TRUE(v8CallBoolean( |
| 73 v8Object->Set(scope.context(), ToV8(&scope, "foo"), ToV8(&scope, 34)))); |
| 74 EXPECT_TRUE(v8CallBoolean(v8Object->DefineOwnProperty( |
| 75 scope.context(), v8String(scope.isolate(), "bar"), ToV8(&scope, -1024), |
| 76 v8::PropertyAttribute::DontEnum))); |
| 77 EXPECT_TRUE(v8CallBoolean( |
| 78 v8Object->Set(scope.context(), ToV8(&scope, "baz"), ToV8(&scope, 42)))); |
| 79 |
| 80 NonThrowableExceptionState exceptionState; |
| 81 const auto& record = |
| 82 NativeValueTraits<IDLRecord<IDLByteString, IDLLong>>::nativeValue( |
| 83 scope.isolate(), v8Object, exceptionState); |
| 84 EXPECT_EQ(2U, record.size()); |
| 85 EXPECT_EQ(std::make_pair(String("foo"), int32_t(34)), record[0]); |
| 86 EXPECT_EQ(std::make_pair(String("baz"), int32_t(42)), record[1]); |
| 87 } |
| 88 { |
| 89 // Exceptions are being thrown in this test, so we need another scope. |
| 90 V8TestingScope scope; |
| 91 v8::Local<v8::Object> originalObject = v8::Object::New(scope.isolate()); |
| 92 EXPECT_TRUE(v8CallBoolean(originalObject->Set( |
| 93 scope.context(), ToV8(&scope, "foo"), ToV8(&scope, 34)))); |
| 94 EXPECT_TRUE(v8CallBoolean(originalObject->Set( |
| 95 scope.context(), ToV8(&scope, "bar"), ToV8(&scope, 42)))); |
| 96 |
| 97 NonThrowableExceptionState exceptionState; |
| 98 const auto& record = |
| 99 NativeValueTraits<IDLRecord<IDLString, IDLLong>>::nativeValue( |
| 100 scope.isolate(), originalObject, exceptionState); |
| 101 EXPECT_EQ(2U, record.size()); |
| 102 |
| 103 v8::Local<v8::Object> handler = v8::Object::New(scope.isolate()); |
| 104 EXPECT_TRUE(v8CallBoolean(handler->Set( |
| 105 scope.context(), ToV8(&scope, "getOwnPropertyDescriptor"), |
| 106 v8::Function::New(scope.context(), ReturnBogusObjectDescriptor) |
| 107 .ToLocalChecked()))); |
| 108 v8::Local<v8::Proxy> proxy = |
| 109 v8::Proxy::New(scope.context(), originalObject, handler) |
| 110 .ToLocalChecked(); |
| 111 ExceptionState exceptionStateFromProxy( |
| 112 scope.isolate(), ExceptionState::ExecutionContext, |
| 113 "NativeValueTraitsImplTest", "IDLRecordTest"); |
| 114 const auto& recordFromProxy = |
| 115 NativeValueTraits<IDLRecord<IDLString, IDLLong>>::nativeValue( |
| 116 scope.isolate(), proxy, exceptionStateFromProxy); |
| 117 EXPECT_EQ(0U, recordFromProxy.size()); |
| 118 EXPECT_TRUE(exceptionStateFromProxy.hadException()); |
| 119 EXPECT_TRUE(exceptionStateFromProxy.message().isEmpty()); |
| 120 v8::Local<v8::Value> v8Exception = exceptionStateFromProxy.getException(); |
| 121 EXPECT_TRUE(v8Exception->IsString()); |
| 122 EXPECT_TRUE( |
| 123 v8String(scope.isolate(), "bogus!") |
| 124 ->Equals(v8Exception->ToString(scope.context()).ToLocalChecked())); |
| 125 } |
| 126 { |
| 127 v8::Local<v8::Object> v8Object = v8::Object::New(scope.isolate()); |
| 128 EXPECT_TRUE(v8CallBoolean( |
| 129 v8Object->Set(scope.context(), ToV8(&scope, "foo"), ToV8(&scope, 42)))); |
| 130 EXPECT_TRUE(v8CallBoolean( |
| 131 v8Object->Set(scope.context(), ToV8(&scope, "bar"), ToV8(&scope, 0)))); |
| 132 EXPECT_TRUE(v8CallBoolean(v8Object->Set(scope.context(), ToV8(&scope, "xx"), |
| 133 ToV8(&scope, true)))); |
| 134 EXPECT_TRUE(v8CallBoolean(v8Object->Set( |
| 135 scope.context(), ToV8(&scope, "abcd"), ToV8(&scope, false)))); |
| 136 |
| 137 NonThrowableExceptionState exceptionState; |
| 138 const auto& record = |
| 139 NativeValueTraits<IDLRecord<IDLByteString, IDLBoolean>>::nativeValue( |
| 140 scope.isolate(), v8Object, exceptionState); |
| 141 EXPECT_EQ(4U, record.size()); |
| 142 EXPECT_EQ(std::make_pair(String("foo"), true), record[0]); |
| 143 EXPECT_EQ(std::make_pair(String("bar"), false), record[1]); |
| 144 EXPECT_EQ(std::make_pair(String("xx"), true), record[2]); |
| 145 EXPECT_EQ(std::make_pair(String("abcd"), false), record[3]); |
| 146 } |
| 147 { |
| 148 v8::Local<v8::Array> v8StringArray = v8::Array::New(scope.isolate(), 2); |
| 149 EXPECT_TRUE(v8CallBoolean(v8StringArray->Set( |
| 150 scope.context(), ToV8(&scope, 0), ToV8(&scope, "Hello, World!")))); |
| 151 EXPECT_TRUE(v8CallBoolean(v8StringArray->Set( |
| 152 scope.context(), ToV8(&scope, 1), ToV8(&scope, "Hi, Mom!")))); |
| 153 EXPECT_TRUE(v8CallBoolean(v8StringArray->Set( |
| 154 scope.context(), ToV8(&scope, "foo"), ToV8(&scope, "Ohai")))); |
| 155 |
| 156 NonThrowableExceptionState exceptionState; |
| 157 const auto& record = |
| 158 NativeValueTraits<IDLRecord<IDLUSVString, IDLString>>::nativeValue( |
| 159 scope.isolate(), v8StringArray, exceptionState); |
| 160 EXPECT_EQ(3U, record.size()); |
| 161 EXPECT_EQ(std::make_pair(String("0"), String("Hello, World!")), record[0]); |
| 162 EXPECT_EQ(std::make_pair(String("1"), String("Hi, Mom!")), record[1]); |
| 163 EXPECT_EQ(std::make_pair(String("foo"), String("Ohai")), record[2]); |
| 164 } |
| 165 { |
| 166 v8::Local<v8::Object> v8Object = v8::Object::New(scope.isolate()); |
| 167 EXPECT_TRUE(v8CallBoolean(v8Object->Set( |
| 168 scope.context(), v8::Symbol::GetToStringTag(scope.isolate()), |
| 169 ToV8(&scope, 34)))); |
| 170 EXPECT_TRUE(v8CallBoolean( |
| 171 v8Object->Set(scope.context(), ToV8(&scope, "foo"), ToV8(&scope, 42)))); |
| 172 |
| 173 NonThrowableExceptionState exceptionState; |
| 174 const auto& record = |
| 175 NativeValueTraits<IDLRecord<IDLString, IDLShort>>::nativeValue( |
| 176 scope.isolate(), v8Object, exceptionState); |
| 177 EXPECT_EQ(1U, record.size()); |
| 178 EXPECT_EQ(std::make_pair(String("foo"), int16_t(42)), record[0]); |
| 179 } |
| 180 { |
| 181 v8::Local<v8::Object> v8Object = v8::Object::New(scope.isolate()); |
| 182 EXPECT_TRUE(v8CallBoolean(v8Object->Set( |
| 183 scope.context(), v8::Symbol::GetToStringTag(scope.isolate()), |
| 184 ToV8(&scope, 34)))); |
| 185 EXPECT_TRUE(v8CallBoolean( |
| 186 v8Object->Set(scope.context(), ToV8(&scope, "foo"), ToV8(&scope, 42)))); |
| 187 |
| 188 NonThrowableExceptionState exceptionState; |
| 189 const auto& record = |
| 190 NativeValueTraits<IDLRecord<IDLString, IDLShort>>::nativeValue( |
| 191 scope.isolate(), v8Object, exceptionState); |
| 192 EXPECT_EQ(1U, record.size()); |
| 193 EXPECT_EQ(std::make_pair(String("foo"), int16_t(42)), record[0]); |
| 194 } |
| 195 { |
| 196 v8::Local<v8::Object> v8ParentObject = v8::Object::New(scope.isolate()); |
| 197 EXPECT_TRUE(v8CallBoolean(v8ParentObject->Set( |
| 198 scope.context(), ToV8(&scope, "foo"), ToV8(&scope, 34)))); |
| 199 EXPECT_TRUE(v8CallBoolean(v8ParentObject->Set( |
| 200 scope.context(), ToV8(&scope, "bar"), ToV8(&scope, 512)))); |
| 201 v8::Local<v8::Object> v8Object = v8::Object::New(scope.isolate()); |
| 202 EXPECT_TRUE( |
| 203 v8CallBoolean(v8Object->SetPrototype(scope.context(), v8ParentObject))); |
| 204 |
| 205 NonThrowableExceptionState exceptionState; |
| 206 auto record = |
| 207 NativeValueTraits<IDLRecord<IDLString, IDLUnsignedLong>>::nativeValue( |
| 208 scope.isolate(), v8Object, exceptionState); |
| 209 EXPECT_TRUE(record.isEmpty()); |
| 210 |
| 211 EXPECT_TRUE(v8CallBoolean(v8Object->Set( |
| 212 scope.context(), ToV8(&scope, "quux"), ToV8(&scope, 42)))); |
| 213 EXPECT_TRUE(v8CallBoolean(v8Object->Set( |
| 214 scope.context(), ToV8(&scope, "foo"), ToV8(&scope, 1024)))); |
| 215 record = |
| 216 NativeValueTraits<IDLRecord<IDLString, IDLUnsignedLong>>::nativeValue( |
| 217 scope.isolate(), v8Object, exceptionState); |
| 218 EXPECT_EQ(2U, record.size()); |
| 219 EXPECT_EQ(std::make_pair(String("quux"), uint32_t(42)), record[0]); |
| 220 EXPECT_EQ(std::make_pair(String("foo"), uint32_t(1024)), record[1]); |
| 221 } |
| 222 { |
| 223 v8::Local<v8::Array> v8StringArray = v8::Array::New(scope.isolate(), 2); |
| 224 EXPECT_TRUE(v8CallBoolean(v8StringArray->Set( |
| 225 scope.context(), ToV8(&scope, 0), ToV8(&scope, "Hello, World!")))); |
| 226 EXPECT_TRUE(v8CallBoolean(v8StringArray->Set( |
| 227 scope.context(), ToV8(&scope, 1), ToV8(&scope, "Hi, Mom!")))); |
| 228 v8::Local<v8::Object> v8Object = v8::Object::New(scope.isolate()); |
| 229 EXPECT_TRUE(v8CallBoolean(v8Object->Set( |
| 230 scope.context(), ToV8(&scope, "foo"), ToV8(&scope, v8StringArray)))); |
| 231 |
| 232 NonThrowableExceptionState exceptionState; |
| 233 const auto& record = |
| 234 NativeValueTraits<IDLRecord<IDLString, IDLSequence<IDLString>>>:: |
| 235 nativeValue(scope.isolate(), v8Object, exceptionState); |
| 236 EXPECT_EQ(1U, record.size()); |
| 237 EXPECT_EQ("foo", record[0].first); |
| 238 EXPECT_EQ("Hello, World!", record[0].second[0]); |
| 239 EXPECT_EQ("Hi, Mom!", record[0].second[1]); |
| 240 } |
| 241 } |
| 242 |
| 243 } // namespace |
| 244 |
| 245 } // namespace blink |
OLD | NEW |