// Copyright 2017 the V8 project 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 "include/v8-template.h" #include "test/unittests/test-utils.h" #include "testing/gtest/include/gtest/gtest.h" using DictionaryTemplateTest = v8::TestWithContext; namespace v8 { namespace { v8::Local v8_str(v8::Isolate* isolate, const char* x) { return v8::String::NewFromUtf8(isolate, x).ToLocalChecked(); } v8::Local v8_int(v8::Isolate* isolate, int x) { return v8::Integer::New(isolate, x); } } // namespace TEST_F(DictionaryTemplateTest, SetPropertiesAndInstantiateWithoutValues) { HandleScope scope(isolate()); constexpr std::string_view property_names[] = {"a", "b"}; Local tpl = DictionaryTemplate::New(isolate(), property_names); MaybeLocal values[2]; Local instance = tpl->NewInstance(context(), values); EXPECT_FALSE(instance.IsEmpty()); EXPECT_FALSE( instance->HasOwnProperty(context(), v8_str(isolate(), "a")).ToChecked()); EXPECT_FALSE( instance->HasOwnProperty(context(), v8_str(isolate(), "b")).ToChecked()); } TEST_F(DictionaryTemplateTest, SetPropertiesAndInstantiateWithSomeValues) { HandleScope scope(isolate()); constexpr std::string_view property_names[] = {"a", "b"}; Local tpl = DictionaryTemplate::New(isolate(), property_names); MaybeLocal values[2] = {{}, v8_str(isolate(), "b_value")}; Local instance = tpl->NewInstance(context(), values); EXPECT_FALSE(instance.IsEmpty()); EXPECT_FALSE( instance->HasOwnProperty(context(), v8_str(isolate(), "a")).ToChecked()); EXPECT_TRUE( instance->HasOwnProperty(context(), v8_str(isolate(), "b")).ToChecked()); } TEST_F(DictionaryTemplateTest, SetPropertiesAndInstantiateWithAllValues) { HandleScope scope(isolate()); constexpr std::string_view property_names[] = {"a", "b"}; Local tpl = DictionaryTemplate::New(isolate(), property_names); MaybeLocal values[2] = {v8_str(isolate(), "a_value"), v8_str(isolate(), "b_value")}; Local instance = tpl->NewInstance(context(), values); EXPECT_FALSE(instance.IsEmpty()); EXPECT_TRUE( instance->HasOwnProperty(context(), v8_str(isolate(), "a")).ToChecked()); EXPECT_TRUE( instance->HasOwnProperty(context(), v8_str(isolate(), "b")).ToChecked()); } TEST_F(DictionaryTemplateTest, TestPropertyTransitionWithDifferentRepresentation) { HandleScope scope(isolate()); constexpr std::string_view property_names[] = {"q", "a"}; Local tpl = DictionaryTemplate::New(isolate(), property_names); constexpr int32_t kBoxedInt = 1 << 31; MaybeLocal values[2] = {{}, v8_int(isolate(), kBoxedInt)}; Local instance1 = tpl->NewInstance(context(), values); auto value1 = instance1->Get(context(), v8_str(isolate(), "a")).ToLocalChecked(); EXPECT_EQ(Int32::Cast(*value1)->Value(), kBoxedInt); // Now transition from a boxed int to a SMI. constexpr int32_t kSmi = 42; values[1] = v8_int(isolate(), kSmi); Local instance2 = tpl->NewInstance(context(), values); auto value2 = instance2->Get(context(), v8_str(isolate(), "a")).ToLocalChecked(); EXPECT_EQ(Int32::Cast(*value2)->Value(), kSmi); // Now from SMI back to a boxed int again, just in case. values[1] = v8_int(isolate(), kBoxedInt); Local instance3 = tpl->NewInstance(context(), values); auto value3 = instance3->Get(context(), v8_str(isolate(), "a")).ToLocalChecked(); EXPECT_EQ(Int32::Cast(*value3)->Value(), kBoxedInt); } TEST_F(DictionaryTemplateTest, PrototypeContext) { HandleScope scope(isolate()); constexpr std::string_view property_names[] = {"a", "b"}; Local tpl = DictionaryTemplate::New(isolate(), property_names); MaybeLocal fast_values[2] = {v8_str(isolate(), "a_value"), v8_str(isolate(), "b_value")}; MaybeLocal slow_values[2] = {{}, v8_str(isolate(), "b_value")}; Local instance1 = tpl->NewInstance(context(), fast_values); Local object1 = v8::Object::New(isolate()); Local instance2, instance3; Local object2; { Local context2 = Context::New(isolate()); v8::Context::Scope scope(context2); instance2 = tpl->NewInstance(context2, fast_values); instance3 = tpl->NewInstance(context2, slow_values); object2 = v8::Object::New(isolate()); } EXPECT_TRUE(instance1->GetPrototypeV2() == object1->GetPrototypeV2()); EXPECT_TRUE(instance2->GetPrototypeV2() == object2->GetPrototypeV2()); EXPECT_FALSE(instance1->GetPrototypeV2() == instance2->GetPrototypeV2()); EXPECT_TRUE(instance2->GetPrototypeV2() == instance3->GetPrototypeV2()); } } // namespace v8